簡體   English   中英

當寫一個返回指針的 function 時,為什么要分配 memory 給我要返回的指針?

[英]When writing a function that returns pointer, why should I allocate memory to the pointer I'm going to return?

當談到 memory 分配和指針時,我有點弱。 所以,我想了解為什么我必須將 memory 分配給函數中的指針,如下所示:

char *cstring(char c, int n)
{
int i = 0;
char * res;
res = malloc ((n+1)*sizeof(char));
while (i<n)
{
    res[i]=c;
    i++;
}
res[i] ='\0';
return res;
}

為什么以下無效?

char *cstring(char c, int n)
{
int i = 0;
char * res;
while (i<n)
{
    res[i]=c;
    i++;
}
res[i] ='\0';
return res;
}

我知道我應該(通常)將 memory 分配給指針,以便它們定義 memory。 但是,我想主要了解它與堆棧和堆內存的概念有什么關系! 提前致謝!

指針需要指向有效的 memory 位置,然后才能取消引用。

在您的第一個示例中, res指向分配的 memory 塊,隨后可以對其進行寫入和讀取。

在您的第二個示例中,當您嘗試取消引用res時,它保持未初始化 這會導致未定義的行為 在這種情況下,最可能的結果是,它包含的任何垃圾值都不是有效的 memory 地址,因此當您嘗試取消引用該無效地址時,您的程序將崩潰。

您的代碼的第二個版本聲明了一個指針,但沒有將其初始化為指向一個有效的 memory 地址。

然后,代碼在循環期間取消引用該指針。 因此,在這種情況下,您的代碼將訪問未初始化的 memory。 請記住,數組索引只是解除引用的語法糖——因此您的代碼訪問 memory 是不應該的。


您的代碼的第一個版本將指針初始化為實際指向某物,因此當您在循環期間取消引用它時,它可以工作。

當然,無論哪種情況,您都從 function 返回指針——它只是在第一個版本中指向有效的東西,而在第二個版本中它指向任何地方


這里的道德是始終初始化您的變量。 不這樣做可能會導致代碼中出現未定義的行為(即使它有時似乎可以工作)。 這里的一般建議是始終使用至少一些編譯標志來編譯您的代碼。 例如在gcc / clang中,考慮-Wall -Werror -Wextra 此類選項通常適用於未初始化變量的簡單情況。

此外, valgrind是 memory 分析的出色工具。 它可以在運行時輕松檢測未初始化的 memory 的使用,以及 memory 泄漏。

如果你聲明一個這樣的變量,

int A = 5;

那么這意味着變量將在堆棧上。 當函數被調用時,它們的局部變量被壓入堆棧。 主要的 function 也是一個例子。 因此,您不必手動分配 memory,您的編譯器將在后台為您執行此操作,然后再調用您的主 function。 這也意味着如果您在執行 function 期間檢查堆棧,您可以看到值 5。

有了這個,

int  A = 5;
int *PtrToA = &A;

指針將再次在堆棧上。 但是這一次,堆棧上的值只是顯示了我們想要的實際 integer 值的 memory 地址。 它指向保存值 5 的 memory 塊的地址。由於此處 A 保存在堆棧中,因此指針將顯示堆棧上的 memory 地址。 就像您問題中的情況一樣,您可以動態分配 memory 。 但是您必須在閱讀之前對其進行初始化。 因為當您請求分配 memory 時,您的操作系統會在程序堆中搜索有效的 memory 字段並為您保留該字段。 比它還給你它的地址並給你讀寫權限,所以你可以使用它。 但是其中的值不會包含您想要的。 當編譯器在堆棧上分配時,初始值將再次取消設置。 如果你這樣做,

char *res;
res[1] = 3;

變量 res 將在堆棧上,它將包含一些隨機值。 所以訪問它就是這樣,

(rand())[1] = 3;

您可能會收到訪問沖突錯誤,因為您可能無權寫入該 memory 位置。

重要說明; 在您的 function 調用返回后,堆棧上的局部變量值不再有效。 所以要小心。 在 function 調用結束后不要取消引用它們。

綜上所述; 如果要使用指針,請確保它指向有效的 memory 位置。 你可以自己分配或者讓它指向另一個memory地址。

很簡單:因為您沒有為您寫入的數據分配任何 memory。 在您的示例中,您定義了指針,您沒有對其進行初始化,因此它將引用 memory 中的隨機(或者更確切地說不可能預測)位置,然后您嘗試寫入此隨機 memory 位置。

您在 5 行示例中有 2 個未定義的行為。 你的指針沒有初始化,並且你沒有分配任何有效的 memory 這個指針來引用。

編輯:

有效的

char *cstring(char c, int n)
{
    char * res;
    res = malloc ((n+1)*sizeof(char));
char *cstring(char c, int n)
{
    char * res;
    static char buff[somesize];
    res = buff;
char buff[somesize];
char *cstring(char c, int n)
{
    char * res;
    res = buff;

無效的

char *cstring(char c, int n)
{
    char * res;
    char buff[somesize];
    res = buff;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM