缩小指针所占用的内存时的realloc行为

时间:2011-11-10 18:28:39

标签: c realloc

困惑1
man realloc表示如果必须执行新分配以将对象调整为新大小,则将移动该对象。但是,在缩小规模时,有很多地方都说it is possible to move data in memory to a new place(SO)。这让我感到困惑。我们如何发现缩小规模将在新的分配中失败,因为在手册页和gnu page中没有明确提到减小大小的情况。

困惑2
当我们做以下时:

void * ptr1 = malloc(SOMEBIGSIZE);
void * ptr2 = realloc(ptr1, SOMESMALLSIZE);

评估ptr1==ptr2结果为真。这意味着ptr2指向相同的ptr1。那么,2.1或2.2中的哪一个是真的? (2.1) ptr1没有缩小尺寸,如果SOMEBIGSIZE>>> SOMESMALLSIZE可能会很糟糕,我们在内存方面没有任何优势。
(2.2)如果ptr1缩小,那么地址范围ptr1 + SOMESMALLSIZE到ptr1 + SOMEHUGESIZE的内存会发生什么变化?它被释放或标记为免费吗?

5 个答案:

答案 0 :(得分:6)

C标准从用户程序的角度讲述了realloc的行为。它没有定义实现。

以下是实施标准规定的相关要求(在您的Q中询问)。

C99标准7.20.3.4-1:重新分配功能:

  

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

C99标准7.20.3.4-4:

  

realloc函数返回一个指向新对象(可能与指向旧对象的指针具有相同值)的指针,如果无法分配新对象,则返回空指针。< / p>

答案 1 :(得分:2)

关于你的第一次困惑,你真的需要更好地阅读gnu页面。

  

在几个分配实现中,将块缩小有时需要复制它,因此如果没有其他可用空间,它可能会失败。

现在,对于第二个混乱,两者中的任何一个都是可能的。它取决于malloc的特定实现,并且没有限制(我知道)要求一个特定情况始终为真。

答案 2 :(得分:0)

我认为规范并不禁止realloc在这种情况下不做任何事情。

但是如果ptr1==ptr2并且系统malloc功能不是太愚蠢,我会想象它可以将未使用的内存范围标记为可​​重用的未来malloc - s,或有时候将它返回给系统(例如在Posix上使用munmap系统调用)。

我对标准的(有限)理解使我认为总是返回malloc的空指针并且对realloc没有任何作用的实现仍然尊重这封信(但不是精神)标准。

答案 3 :(得分:0)

那是事情。您永远不知道realloc何时将分配另一个内存块并复制数据,因为没有API允许您查看“malloc”内部,并查看分配的区域是否可以扩展或缩小。

答案 4 :(得分:0)

这里的重要教训是,该标准描述了malloc()/realloc()效果,而不是他们实际做的。这样做是为了让标准库自由的实现者能够对这些函数的行为进行优化,剪切或更改,而不会影响使用它们的代码。 该标准阻止您对智能或正在发生的事情做出假设,因为它可能不是。

从程序员的角度来看,这可能是分配器(少了一些错误检查):

  void*
  malloc(size_t amt){
       static char *base = NULL;
       if(base==NULL)
              base = sbrk(0);
       char *c = base+1;
       base=sbrk(amt+5);
       return c;
  }
  void*
  realloc(void *old, size_t amt){
        return memcpy(malloc(amt), old, amt);
  }
  void free(void *v){}

我叫她swalloc,愚蠢的浪费分配器。