[英]Is there an alternative way to free dynamically allocated memory in C - not using the free() function?
我正在研究測試,我想知道這些是否相當於免費(ptr):
malloc(NULL);
calloc(ptr);
realloc(NULL, ptr);
calloc(ptr, 0);
realloc(ptr, 0);
根據我的理解,這些都不會起作用,因為free()函數實際上告訴C ptr后面的內存再次可供它使用。 對不起,這是一個noob問題,但是將不勝感激。
實際上,最后一個相當於對free()
的調用。 仔細閱讀realloc()
的規范,你會發現它可以重新分配數據,或者改變分配的大小(特別是如果新的大小比舊的大,可能會移動數據),它也可以釋放記憶。 實際上,你不需要其他功能; 它們都可以用realloc()
來編寫。 並不是說心智正常的人會這樣做......但是可以做到。
請參閱Steve Maguire的“ 編寫實體代碼 ”,以全面剖析malloc()
函數族的危險。 請參閱ACCU網站,以全面剖析閱讀“編寫固體代碼”的危險。 我不相信它和評論一樣糟糕 - 雖然完全缺乏對const
的處理確實可以追溯到它(回到90年代早期,當時C89仍然是新的並且沒有全面實施)。
D McKee關於MacOS X 10.5(BSD)的說明很有意思......
C99標准說:
概要
#include <stdlib.h>
void *malloc(size_t size);
描述
malloc函數為一個對象分配空間,該對象的大小由size指定,其值是不確定的。
返回
malloc函數返回空指針或指向已分配空間的指針。
概要
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
描述
realloc函數釋放ptr指向的舊對象,並返回指向具有size指定大小的新對象的指針。 新對象的內容應與解除分配之前的舊對象的內容相同,直到新舊大小中的較小者為止。 新對象中超出舊對象大小的任何字節都具有不確定的值。
如果ptr是空指針,則realloc函數的行為類似於指定大小的malloc函數。 否則,如果ptr與之前由calloc,malloc或realloc函數返回的指針不匹配,或者如果通過調用free或realloc函數釋放了空間,則行為未定義。 如果無法分配新對象的內存,則不會釋放舊對象,並且其值不會更改。
返回
realloc函數返回指向新對象的指針(可能與指向舊對象的指針具有相同的值),如果無法分配新對象,則返回空指針。
除了由於額外的標題和功能而進行的編輯更改之外,ISO / IEC 9899:2011標准與C99相同,但在7.22.3而不是7.20.3中。
realloc的Solaris 10(SPARC)手冊頁說:
realloc()函數將塊指針的大小更改為ptr to size bytes,並返回指向(可能已移動)塊的指針。 內容將保持不變,直至新舊尺寸中的較小者。 如果塊的新大小需要移動塊,則釋放用於塊的先前實例化的空間。 如果新大小較大,則未指定塊的新分配部分的內容。 如果ptr為NULL,則realloc()的行為類似於指定大小的malloc()。 如果size為0且ptr不是空指針,則釋放指向的空間。
這是一個非常明確的'它就像free()'聲明一樣。
但是,MacOS X 10.5或者BSD說不同的東西再次證實了我的第一段中“他們正確的思想中沒有人”的一部分。
當然,還有C99理由 ......它說:
在這些函數的定義中處理空指針和零長度分配請求部分是由支持這種范例的願望指導的:
OBJ * p; // pointer to a variable list of OBJs
/* initial allocation */
p = (OBJ *) calloc(0, sizeof(OBJ));
/* ... */
/* reallocations until size settles */
while(1) {
p = (OBJ *) realloc((void *)p, c * sizeof(OBJ));
/* change value of c or break out of loop */
}
據報道,這種編碼方式未得到委員會的認可,因此得到廣泛使用。
某些實現已為零字節的分配請求返回了非空值。 雖然這種策略具有區分“無”和“零”(未分配指針與指向零長度空間的指針)的理論優勢,但它具有更迫切的理論缺點,即需要零長度對象的概念。 由於無法聲明此類對象,因此它們可能存在的唯一方法是通過此類分配請求。
C89委員會決定不接受零長度物體的想法。 因此,分配函數可以返回零指針分配請求的空指針。 請注意,這種處理方法並不排除上述范例。
C89的安靜改變
依賴於返回非空指針的大小為零的分配請求的程序將表現不同。
[...]
null第一個參數是允許的。 如果第一個參數不為null,並且第二個參數為0,則調用將釋放第一個參數指向的內存,並且可能返回null參數; C99與不允許零大小對象的策略一致。
C99的一個新功能:更改了realloc函數,以清楚地指出了指向的對象被釋放,分配了一個新對象,並且新對象的內容與舊對象的內容相同,直到較小的對象這兩種尺寸。 C89嘗試指定新對象與舊對象是同一對象,但可能具有不同的地址。 這與標准的其他部分沖突,這些部分假定對象的地址在其生命周期內是恆定的。 此外,當大小為零時,支持實際分配的實現不一定為此情況返回空指針。 C89似乎要求零回報值,委員會認為這個限制性太強。
C89明確地說:“如果size為零且ptr不是空指針,則它指向的對象被釋放。” 所以他們似乎已經刪除了C99中的那個句子?
是的,他們刪除了這句話,因為它被開頭的句子包含在內:
realloc函數釋放ptr指向的舊對象
那里沒有蠕動的空間; 舊對象被釋放。 如果請求的大小為零,則返回malloc(0)
可能返回的任何內容,這通常(通常)是一個空指針,但可能是一個非空指針,也可以返回到free()
但是不能合法地返回解引用。
realloc(ptr, 0);
相當於free(ptr);
(雖然我不建議使用它!)
另外:這兩個調用彼此相同(但不是免費的):
realloc(NULL,size)
malloc(size)
最后一個 - realloc(ptr, 0)
很接近。 它將釋放任何已分配的塊並用最小的分配替換它(我的Mac OS X 10.5聯機幫助頁)。 檢查您的本地聯機幫助頁以查看它在您的系統上執行的操作。
也就是說,如果ptr
指向一個實質性的對象,你將獲得大部分內存。
Debian Lenny的手冊頁與Mitch和Jonathan一致 ...... BSD真的與Linux有分歧嗎?
從違規手冊頁:
realloc()函數嘗試將ptr指向的分配大小更改為size,並返回ptr。 [...]如果size為零且ptr不為NULL,則分配一個新的最小大小的對象並釋放原始對象。
linux和solaris手冊頁非常干凈,'89標准: realloc(ptr,0)
就像free(ptr)
。 上面的Mac OS手冊頁和Jonathan引用的標准不太清楚,但似乎留下了打破等價的空間。
我一直想知道為什么會有這樣的區別:“像免費一樣”的解釋對我來說似乎很自然。 我可以訪問的兩個實現包括一些環境變量驅動的可調性,但BSD版本接受更多選項一些示例:
MallocGuardEdges If set, add a guard page before and after each large block.
MallocDoNotProtectPrelude If set, do not add a guard page before large
blocks, even if the MallocGuardEdges envi-
ronment variable is set.
MallocDoNotProtectPostlude If set, do not add a guard page after large
blocks, even if the MallocGuardEdges envi-
ronment variable is set.
和
MallocPreScribble If set, fill memory that has been allocated with 0xaa bytes. This increases the likeli- hood that a program making assumptions about the contents of freshly allocated memory will fail.
MallocScribble If set, fill memory that has been deallo-
cated with 0x55 bytes. This increases the
likelihood that a program will fail due to
accessing memory that is no longer allo-
cated.
在正常模式下,“最小尺寸物體”可能沒什么(即相當於free
),但是某些防護裝置就位。 把它拿走它的價值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.