realloc实际上是否会缩减常见实现中的缓冲区?

Fre*_*Foo 11 c python malloc memory-management numpy

在常见的实现中,例如Linux/Glibc,Windows/MSVC和BSD/Mac OS X,将会

void *p = malloc(N + M);  // assume this doesn't fail
p = realloc(p, N);        // nor this
Run Code Online (Sandbox Code Playgroud)

N,M > 0实际上收缩返回的缓冲区mallocrealloc调用,在这个意义上,高达M字节可以返回到空闲列表?更重要的是,它是否有可能重新分配缓冲区?

我想知道,因为我刚刚在上面实现了动态数组numpy.ndarray,而我正在做一个resize调用realloc,以获得最终的大小.我可以跳过决赛resize作为优化(以牺牲永久性分配为代价),我想知道这是否值得尝试.

fgh*_*ghj 16

我可以说Linux/glibc.在源代码中,它包含如下注释:

如果n字节数少于已经保留的字节数p,则新使用的
空间将被删除并尽可能释放.

如果你看一下glibc的代码,它包含这样的行:

remainder_size = newsize - nb;

if (remainder_size < MINSIZE) { /* not enough extra to split off */
  set_head_size(newp, newsize | (av != &main_arena ? NON_MAIN_ARENA : 0));
  set_inuse_bit_at_offset(newp, newsize);
}
else { /* split remainder */
  remainder = chunk_at_offset(newp, nb);
  set_head_size(newp, nb | (av != &main_arena ? NON_MAIN_ARENA : 0));
  set_head(remainder, remainder_size | PREV_INUSE |
       (av != &main_arena ? NON_MAIN_ARENA : 0));
  /* Mark remainder as inuse so free() won't complain */
  set_inuse_bit_at_offset(remainder, remainder_size);
 #ifdef ATOMIC_FASTBINS
  _int_free(av, remainder, 1);
 #else
  _int_free(av, remainder);
 #endif
}
Run Code Online (Sandbox Code Playgroud)

nb- newsize应该调用你想要的字节数oldsize.所以如果可能的话,它试图释放多余的东西.

关于Mac OSX.更确切地说magazine_malloc,目前malloc来自Apple的实施.有关详细信息,请参见http://cocoawithlove.com/2010/05/look-at-how-malloc-works-on-mac.html.

realloc调用区域realloc方法,我看到它的当前实现szone_realloc.对于不同的分配大小存在不同的代码,但算法总是相同的:

if (new_good_size <= (old_size >> 1)) {
            /*
             * Serious shrinkage (more than half). free() the excess.
             */
            return tiny_try_shrink_in_place(szone, ptr, old_size, new_good_size);
} else if (new_good_size <= old_size) {
            /* 
             * new_good_size smaller than old_size but not by much (less than half).
             * Avoid thrashing at the expense of some wasted storage.
             */
             return ptr;
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它的实现会检查它new_size <= old_size / 2,如果是这样,那么就会释放内存,如果没有,它就什么都不做.