当缓冲区收缩时,realloc是否保证就位?

时间:2010-07-02 00:06:36

标签: c++

是否有任何保证realloc()将始终缩小缓冲区?以下是:

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

将始终给new_ptr == old_ptr 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
}

即使数据类型具有自引用/指针或其他任何内容,我仍然期望就地“缩小”会很强大......

5 个答案:

答案 0 :(得分:8)

没有

就是这样。这些“它可能在一些架构中起作用”或“它应该基于经验”。该标准明确规定地址可能会发生变化,因此依赖 而已。在任何情况下,你都询问它是否保证 - 答案是肯定的没有(a)

在编码标准方面:做或不做。没有“尝试”: - )


来自c99:

  

realloc函数释放ptr指向的旧对象,并返回指向size指定大小的新对象的指针。新对象的内容应与解除分配之前的旧对象的内容相同,直到新旧大小中的较小者为止。新对象中超出旧对象大小的任何字节都有不确定的值。

     

如果ptr是空指针,则realloc函数的行为类似于指定大小的malloc函数。否则,如果ptr与先前由callocmallocrealloc函数返回的指针不匹配,或者如果通过调用{free已释放空间{1}}或realloc函数,行为未定义。如果无法分配新对象的内存,则不会释放旧对象,并且其值不会更改。

     

realloc函数返回指向新对象的指针( 可能 与指向旧对象的指针具有相同的值),或者为null指针如果无法分配新对象。


(a)如果您想知道为什么,您不会将缓冲区分成两个较小的缓冲区(保留一个缓冲区并将另一个缓冲区返回到空闲列表中)为了提高效率,至少有一种可能性让人想起。

如果您有不同大小的分配池(例如,可能使用不同的分配策略),则可以将数据移到池中以进行较小的分配。从单独的池中获得的效率提升可能会超过留下内存的收益。

但这只是一个例子,我不知道是否有任何实现。如上所述,您应该依赖标准的要求,即即使缩小时内存也可能会移动。

答案 1 :(得分:6)

没有。你不应该依赖它。

根据规范7.20.3.4/4:

  

realloc函数返回一个指针   到新对象(可能拥有   与指向的指针值相同   旧对象)或空指针   如果新对象不能   分配

答案 2 :(得分:3)

一般来说确实如此,但它没有保证(这完全取决于你的架构)。所以你不应该依赖这种行为

编辑:

参考:http://opengroup.org/onlinepubs/007908775/xsh/realloc.html

  

成功完成大小   不等于0,realloc()返回一个   指针(可能移动)   分配空间。

答案 3 :(得分:2)

一些分配器使用“bucketizing”策略,其中从2 ^ 3到2 ^ 4的大小分配到同一个分配桶。这往往可以防止内存碎片的极端情况,其中许多小分配遍布堆,防止大量分配成功。显然,在这样的堆管理器中,减小分配的大小可能会迫使它进入不同的存储桶。

答案 4 :(得分:1)

不,没有这样的保证。 realloc的实现可能只是缩小了缓冲区的位置,但它们并不限制这样做。