2011-08-16 96 views
20

約在C realloc函數簡單問題: 如果我使用realloc的縮小,一個指針指向的內存塊,沒有「額外」的內存釋放得到?還是需要以某種方式手動釋放?使用realloc的縮小分配的內存

例如,如果我這樣做

int *myPointer = malloc(100*sizeof(int)); 
myPointer = realloc(myPointer,50*sizeof(int)); 
free(myPointer); 

請問我有內存泄漏?

+1

嚴格來說,有一個內存泄漏,因爲你不記錄'realloc'的結果,因此你不可能釋放它。但正如R ..的答案所表明的那樣,你可能在實現細節上感到幸運。 –

+1

哎呀,你是對的。我試圖糾正它。現在怎麼樣? –

+6

如果'realloc'失敗,新代碼仍會泄漏原始分配。我希望大多數實現永遠不會縮小塊,但它是允許的。調用realloc的正確方法,無論是增長還是縮小塊,都是'void * tmp = realloc(myPointer,50 * sizeof(int));如果(!tmp){/ *以某種方式處理錯誤。 myPointer仍然指向仍然分配的舊塊* /} myPointer = tmp;'。 –

回答

16

不,你不會有內存泄漏。 realloc將簡單地將其餘的「可用」標記爲將來的malloc操作。

但是你還是要freemyPointer以後。順便說一句,如果你使用0作爲realloc大小,它會作爲一些實現free同樣的效果。正如Steve Jessop和R ..在評論中所說的,你不應該依賴它。

+3

「如果您在realloc中使用0作爲大小,它將具有與空閒相同的效果。」 - 在您的實施中可能是正確的,但不能保證。如果'realloc'從0輸入返回空指針,並且沒有將errno設置爲ENOMEM,則釋放內存。但是就像malloc一樣,realloc可以嘗試返回0可用大小的實際分配。要求實施文件(7.20.3/1)。 –

+2

Steve是對的,這樣做的實際結果就是你永遠不應該調用大小爲0的'realloc'。處理所有可能的行爲,不符合實現的實現的存在,以及C和POSIX人們似乎不同意什麼是符合性的,什麼不符合依賴與realloc(x,0)有關的任何事情。 –

+0

@Steve Jessop,R ..謝謝澄清:-)我從來沒有打算檢查POSIX以外的內容,我不知道它是非C標準的。 – cnicutar

11

有絕對不是一個內存泄漏,但任何的至少三件事情,當你調用realloc,以減少大小會發生:

  1. 實現在新的請求的長度和釋放拆分分配的內存塊末尾未使用的部分。
  2. 該實現使用新大小進行新分配,將舊內容複製到新位置,並釋放整個舊分配。
  3. 執行什麼都不做。

選項3將是一個相當糟糕的實現,但完全合法的;仍然沒有「內存泄漏」,因爲如果您稍後請撥打free,整個內容仍將被釋放。

至於選項1和2,哪一個更好取決於您是否喜歡性能或避免內存碎片。我相信大多數現實世界的實現將朝着做選項1.

+0

當你需要**減少分配的內存時,選項2背後的原因是什麼?我無法弄清楚。 – Jacob

+1

假設您分配了100個字節,並且希望將其大小調整爲50個字節。第一個分配佔用100個字節的空閒區域,而選項1給出一個50個字節的空閒區域,但較長的100個字節的區域不再可用。但是,如果另一個空閒區只有50個字節長,則選項2可以將數據移動到該位置並釋放100個字節的區域,從而減少內存碎片。 –

+0

請注意,如果您的目標是針對最小碎片進行優化,則只有在較小的可用區域足以容納分配的情況下采用選項2纔有意義。如果你必須從系統中獲得更多的內存或者拆分另一個更大的免費區域,那麼它只能使碎片變得更糟,而不是更好。 –

3

在你給你的代碼的方式傾斜,是的,它可能有泄漏。 realloc的想法是它可以爲您返回一個新的數據位置。就像你在你的問題中做的那樣,你會失去那個指向realloc的指針。

int *myPointer2 = realloc(myPointer,50*sizeof(int)); 
assert(myPointer2); 
myPointer = myPointer2; 
+0

@R ..其實我並不太確定,這就是爲什麼我不只是把它在評論中。如果你想到這個問題,他們會問他的問題,想知道「備用」內存會發生什麼更自然。 –

4

如果realloc失敗,新代碼仍會泄漏原始分配。我希望大多數實現永遠不會縮小塊,但它是允許的。調用realloc的正確方法,無論是增長還是縮小塊,都是void * tmp = realloc(myPointer,50 * sizeof(int));如果(!tmp){/ *以某種方式處理錯誤。 myPointer仍然指向仍然分配的舊塊* /} myPointer = tmp ;. - 史蒂夫·傑索普48分鐘前

嘿,我無法弄清楚如何回答您的評論,對不起。

我是否需要將tmp轉換爲myPointer的類型?在這種情況下,我需要寫

myPointer = (int*)tmp 

而且,在這種情況下,當我做 免費(myPointer) 內存指向由TMP將被釋放,以及,對不對?所以不需要做

free(myPointer) 
free(tmp) 
+0

Realloc仍然會泄漏。這是正確的答案。至少在Windows 7上,64位(tdm-gcc64) – dns