2017-09-28 91 views
2

我想在下面的程序中使用realloc重新分配內存,並在使用malloc(i =(int *)malloc(5 * sizeof(int))malloc)仍然存在或不存在的realloc初始內存之後檢查,使用下面的程序我能夠訪問realoc後,我通過使用另一個指針(即* m)檢查的數據。這是正確的行爲?或一旦realloc調用內存應該是免費的?是否可以釋放現有內存?

#include <stdio.h> 
    #include <stdlib.h> 

    int main() 
    { 
     int *i,*jn, *m; 
     i = (int*)malloc(5 * sizeof(int)); 
     int j,k=10; 

     for(j=0 ;j<5; j++) 
     { 
     i[j] = j; 
     printf("%d \n",i[j]); 
     } 

     for(j=0 ;j<5; j++) 
     { 
     printf("%p\n",i++); 
     } 

     jn = (int *)calloc(5, sizeof(*i)); 

     for(j=0 ;j<5; j++) 
     { 
     printf("%p\n",jn++); 
     } 

     i = i-5; 
     m = i; 

     printf("m = %p %d\n",(m+1), *(m+1)); 

     i =(int *)realloc(i,8*sizeof(int)); 

     for(j=0 ;j<8; j++) 
     { 

     printf("%d\n",i[j]); 
     } 

     for(j=0 ;j<8; j++) 
     { 

     printf("%p\n",i++); 
     } 
     printf("m = %p %d\n",(m+1), *(m+1)); 

     return 0; 
} 
+1

我會考慮這是一個所有權問題,而不是一個具體的行動。如果'realloc'成功,它將獲得傳入內存的所有權(操縱它或者釋放它)並返回一個可以被調用函數使用(「擁有」)的指針。如果'realloc'失敗(返回'NULL'),你的函數保留原始內存的所有權,並且在它完成時應該釋放它。 – Myst

回答

4

首先,realloc可能決定

  1. 分配一個新的內存塊,複製數據,並釋放原來的一個,或

  2. 簡單的擴張/收縮原塊」地方「而不分配新的。

它會選擇哪種方法取決於實施和各種其他外部因素。它可能會遵循第一種方法。或者它可能會遵循第二種方法。通過比較realloc之後的指針im的值,您可以輕鬆找出它遵循的方法。其次,如果realloc決定遵循第一種方法(即分配新的存儲器塊),則舊塊確實被釋放realloc。在這種情況下,嘗試訪問原始內存位置會導致未定義的行爲。

如果realloc決定遵循第二種方法(即擴大或縮小原始存儲塊「原地」),則mi將保持指向相同的位置。在這種情況下,通過m查看相同的數據並不奇怪。

P.S.這意味着您的代碼的行爲是微不足道的undefined。它不能真正用於分析行爲是否「適當」。如果記憶確實被釋放,你期望會發生什麼?

+2

C11標準說(§7.22.3。5):''realloc''函數釋放'ptr'指向的舊對象,並返回一個指向size的指定大小的新對象的 指針。 ...如果分配給新對象的內存不能爲 ,則舊對象不會被釋放並且其值不變。 ...'realloc'函數返回一個指向新對象的指針(它可能與指向舊對象的指針具有相同的 值),或者如果新對象不能被分配爲 ,則返回空指針。C99表示相同。 C90並不清楚被釋放的舊內存,與C99和C11不同。 –

+0

從以上代碼我得到以下輸出。(0 0x9a40008 0x9a4000c 0x9a40010 0x9a40014 0x9a40018 0x9a40020 0x9a40024 0x9a40028 0x9a4002c 0x9a40030 米= 0x9a4000c 1 0x9a40038 0x9a4003c 0x9a40040 0x9a40044 0x9a40048 0x9a4004c 0x9a40050 0x9a40054 米= 0x9a4000c 1)與該輸出如果realloc的釋放舊存儲器如何來*米指針能夠訪問舊存儲位置和其存在於舊存儲的數據location –

+0

@SumitNaik訪問釋放的內存會導致*未定義的行爲*,這可能以不同的方式表現出來。它可能似乎「看到」舊的價值觀。真正的問題在於你甚至在乎的原因。即使你能夠以某種方式訪問​​釋放的內存,「存儲」的殘留數據也是垃圾。這並不意味着什麼。 – AnT

3

realloc等同於:

void * 
realloc(void *old, size_t newsz) 
{ 
    size_t old_sz = internal_function_that_finds_old_size(old); 
    void *new = malloc(newsz); 
    if (new == NULL) 
     return NULL; 
    memcpy(new, old, oldsz); 
    free(old); 
    return new; 
} 

realloc可以做一些更有效的,包括不改變指針,只是讓大小分配更大,它可以使用內核設施到別的地方映射內存中,避免複製等等。但總的來說realloc應該被視爲正是我上面寫的,因爲這是最糟糕的情況。

現在,談到你的程序。你通過無效指針觸摸內存,任何事情都可能發生。在致電realloc之後,m停止爲有效指針。這並不意味着任何人都不會阻止你使用它,它只是意味着如果你使用它,你的程序不再保證做任何明智的事情。

+1

以藍色突出顯示的'new'! –

+0

@MatteoItalia heh。我想SO上的語法高亮相信C/C++神話。 – Art