2010-07-02 42 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