如果您有一个动态分配的缓冲区,它在运行时以无法预测的方式(例如 vector 或字符串)改变其大小,则一种优化其分配的方法是仅以2的幂(或其他一些边界/阈值),并保留多余的空间。这有助于分摊寻找新的可用内存和复制数据的成本,但要花一点额外的内存。例如,许多C++ STL容器的接口(interface)规范(保留,调整大小,修剪)都考虑了这种方案。
我的问题是在Linux 3.0 x86_64,GLIBC 2.13,GCC 4.6(Ubuntu 11.10)上的malloc/realloc/free内存管理器的默认实现是否进行了这样的优化?
void* p = malloc(N);
... // time passes, stuff happens
void* q = realloc(p,M);
换句话说,对于N和M的哪个值(或在其他情况下),p == q?
最佳答案
来自http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=12d2211b0d6603ac27840d6f629071d1c78586fe;hb=HEAD的glibc主干中的realloc实现
首先,如果内存是通过mmap()而不是sbrk()获得的,那么glibc malloc会对大型请求执行此操作,默认情况下> = 128 kB IIRC:
if (chunk_is_mmapped(oldp))
{
void* newmem;
#if HAVE_MREMAP
newp = mremap_chunk(oldp, nb);
if(newp) return chunk2mem(newp);
#endif
/* Note the extra SIZE_SZ overhead. */
if(oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */
/* Must alloc, copy, free. */
newmem = public_mALLOc(bytes);
if (newmem == 0) return 0; /* propagate failure */
MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ);
munmap_chunk(oldp);
return newmem;
}
(Linux具有mremap(),因此实际上就是这样做的)。
对于较小的请求,我们在下面几行
newp = _int_realloc(ar_ptr, oldp, oldsize, nb);
_int_realloc在此处需要复制粘贴很大,但是您会在上面链接的第4221行开始找到它。 AFAICS,它不会像C++ std::vector可以,但是确切地分配用户请求的数量(四舍五入到下一个块边界+对齐内容,依此类推)。
我想这个想法是,如果用户希望此大小增加2的因子(或任何其他常数因子的增加,以确保多次调整大小时的对数效率),那么用户可以在由C库。