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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM