2010-07-02 84 views
9

是否有任何保證realloc()將始終在原地收縮緩衝區?所以,下面的:當緩衝區縮小時,realloc是否保證就地運行?

new_ptr = (data_type *) realloc(old_ptr, new_size * sizeof(data_type)); 

總會給new_ptr == old_ptr如果new_size < old_size(當然除了當new_size == 0)。對我來說,這似乎是合理的,但它對這個標準是否強制執行感到好奇。

我看非POD數據類型的數組的重新分配,如果上述行爲是有保障的想法,以下策略可能至少能讓高效「縮水」:

if (new_size > old_size) 
{ 
    // malloc() a new buffer 
    // use placement copy constructor to copy old objects over 
    // free() old buffer 
} 
else 
if (new_size < old_size) 
{ 
    // explicit destruction of unneeded objects 
    // realloc() buffer 
} 

我「m期望即使數據類型有自己的引用/指針或任何其他地方的就地」收縮「將是強大的...

+0

感謝您的評論大家。我想我只是覺得它非常浪費和效率不高,不得不分配一個新的緩衝區,並做一個完整的副本,以實現「收縮」... – 2010-07-02 00:34:45

+0

不會添加到這裏的「不」的合唱團,你應該得到現在的想法。但是,保證重新分配的塊在收縮時重用同一內存的一個非預期的副作用是您無法使用[小對象分配器](http://www.developer.com/ws/brew/article.php/3315011 /Small-Memory-Allocation.htm)在malloc/realloc中,因爲這些分配器將相同大小的對象組合在一起。 – 2010-07-02 00:37:10

+0

另一個不能指望realloc始終重用相同內存的原因是,大多數通用堆將管理信息(塊大小,指向堆中下一個塊的指針)放在分配內存「前面」的標題中。因此,如果你有一個坐在兩個分配塊之間的塊,並且只讀出一個較小的塊,那麼就沒有空間爲釋放的內存單詞放置標題,實際上會丟失它並永久分割你的堆。 – 2010-07-02 00:40:57

回答

7

編號

就是這樣。沒有一個「它可以在某些體系結構中工作」或「它應該根據經驗」。該標準明確指出,地址可能會改變,所以依靠,僅此而已。

從編碼到標準方面:做或不做。沒有「嘗試」 :-)


從C99:

的realloc函數將釋放舊的對象ptr指向並返回一個指針到擁有指定大小的新對象尺寸。新對象的內容應與釋放前舊對象的內容相同,最大爲新舊對象的最小值。新對象中超出舊對象大小的任何字節都有不確定的值。

如果ptr是空指針,則realloc函數的行爲與指定大小的malloc函數相同。否則,如果ptr與先前由calloc,malloc或realloc函數返回的指針不匹配,或者如果通過調用free或realloc函數釋放空間,則行爲未定義。如果無法分配新對象的內存,則舊對象不會被釋放並且其值不變。如果新對象無法 分配

的realloc函數返回一個指向新的對象(其可以具有相同 值作爲一個指針,指向舊的對象),或空指針。

0

不,沒有這樣的保證。realloc的實現可能只是收縮緩衝區的地方,但他們並不拘泥於這樣做。

1

一些分配器使用「bucketizing」策略,其中從2^3到2^4等大小的分配轉到同一個分配桶。這往往會防止內存碎片的極端情況,因爲堆中的許多小分配會阻止成功分配大量內存。顯然,在這樣一個堆管理器中,減小分配的大小可能會迫使它到不同的存儲桶。

5

不可以。你不應該依賴這個。

根據規格7.20.3.4/4:

realloc函數返回一個指針 給新的對象(其可以具有 相同的值的指針 舊對象),或者空指針 如果新對象不能被 分配。

+3

+1。 :-D – 2010-07-02 00:29:32

+0

+1歐文的洞察力(: – Poni 2010-07-02 01:37:01