malloc()參數爲0的情況

  問題來自於《程序員面試寶典(第三版)》第12.2節問題9(這裏不評價《程序員面試寶典》,就題論題):

下面的代碼片段輸出是什麼?爲什麼?

char *ptr;
if((ptr = (char *)malloc(0))==NULL)
    puts("Got a null pointer");
else
    puts("Got a valid pointer");

 解析:......故意把0值傳給了函數malloc,得到了一個合法的指針,這就是上面的代碼,該代碼的輸出是"Got a valid pointer"。

 

  這個“解析”根本就沒有解析嘛。好在查資料很方便,《C語言參考手冊》上說“如果請求的長度爲0,則標準C語言函數返回一個null指針或不能用於訪問對象的非null指針。”或者你也可以直接在linux裏man malloc來查閱手冊:

void *malloc(size_t size);

...

malloc() allocates size bytes and returns a pointer to the allocated memory. The memory is not cleared. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

  可見,原題的if是爲了鑑別malloc()返回值是NULL,還是一個唯一的待釋放指針;而不是“解析”中的必然是非NULL的“合法指針”,因此輸出也不是確定的,儘管我用gcc和clang多次編譯運行,輸出都是"Got a valid pointer"。

  順便再說說後面的代碼,同樣出自《程序員面試寶典》:

將程序改成:

char *ptr;
if(int pp = (strlen(ptr=(char *)malloc(0))) == 0)
    puts("Got a null pointer");
else
    puts("Got a valid pointer");

或者

char *ptr;
if(int pp = (sizeof(ptr=(char *)malloc(0))) == 4)
    puts("Got a null pointer");
else
    puts("Got a valid pointer");

如果求ptr的strlen的值和sizeof的值,該代碼的輸出是"Got a null pointer"。

  第一段程序的分析和上面一樣,如果不幸返回了一個唯一的待釋放非NULL指針,行爲不可預測;只不過這個if判斷寫的有些繁瑣:注意到“==”優先級高於"=",而賦值語句的值是其左值。

  此時malloc(0)返回了一個可用於free()釋放的唯一指針(非NULL),而且將它傳給strlen(),返回值爲0,這樣看來,它用'\0'進行填充的(即內容是NULL而非指針指向NULL)。但這一點並沒有在man中提到,個人猜測是和實現有關的。
  除此以外,順便考察了strlen((char*)NULL)的行爲:會導致段錯誤。

  第二段程序呢,sizeof()裏寫了一大堆,其實只是計算了sizeof(char *),在32位機上結果當然是4,而sizeof()裏面的malloc()根本沒有執行。和前面兩段代碼不同,關鍵點不在malloc而是sizeof。

  對於Dic4000提到的問題“實際項目中什麼情況下會給malloc傳0?既然是開闢內存,傳0不是沒有意義嗎?”的個人理解:

1.一般確實不會直接寫malloc(0),但是可能在程序某個地方寫int n;int *p = malloc(n);在別的地方又令n=0,造成了參數爲0的情況。若是無心而爲,可能導致某種bug。如果瞭解malloc(0)的行爲,找bug相對而言會簡單點。

2.面試題各種稀奇古怪的問題都有可能出現,有的面試官認爲考這些邊界條件、特殊參數什麼的能考察一個程序員的功底。

 

其他參考文章:

  @淨壇使者進行的更深一步的挖掘,文章和回覆都很有價值:關於malloc(0)的返回值問題--這兩天的總結與實踐篇

  @garbageMan 談面試題:別太把面試題當回事兒

 

更蛋疼的問題:

  如果給malloc()傳一個負參數會怎麼樣?malloc()的參數是size_t類型,一般是無符號數,負值會被轉化它對應於size_t中的對應值。經我測試,當這個值大於malloc()所能分配的上限時,返回NULL

 

複製代碼
#include <stdio.h>
#include <stdlib.h>

int main() {
    size_t t;
    t = (size_t)-1;
    printf("%u\n",t);
    char * p = malloc(t);
    if(p==NULL)
        printf("NULL\n");
}
複製代碼

 

  (剛剛在stackoverflow上看到的http://stackoverflow.com/questions/17925771/what-happens-when-we-call-malloc-with-negative-paramter


作者:五嶽
出處:http://www.cnblogs.com/wuyuegb2312
對於標題未標註爲“轉載”的文章均爲原創,其版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章