9

我正在编写与操作系统无关的无锁队列,到目前为止效果很好,但是内存管理存在小问题。我不确定它的 gcc 问题还是我的问题。问题:将元素添加到列表时内存会增加,但从列表中删除元素时 (free(elementPointer);) 内存使用量不会改变。

但是当我使用 pthreads 时,N 个生产者和 M 个消费者 (1<N<20, 1<M<20)的内存使用量一直约为 10mb(当尝试添加和删除 ~10kk 元素时),所以看起来免费正在工作。

有趣的是,在 VS 2010(相同的代码,没有线程)中,free 工作正常,内存被释放(监视任务管理器)。

我进行了测试,添加了 1kk 个元素,添加完所有元素后,将所有元素一一删除(无线程)。

Linux - 0.08 秒

Windows ~57 秒

Linux(无免费) - 0.07 秒

Windows(无免费) - 0.9 秒

所以,问题是,为什么没有使用线程时 Linux C 中没有释放内存?如有必要,我可以发布代码。

GCC 版本:4.4.3

4

3 回答 3

11

在许多操作系统上,free()不会再次使内存可用于操作系统,而是“仅”用于新调用malloc(). 这就是为什么您看不到外部内存使用量下降的原因,但是当您通过线程增加新分配的数量时,内存会被重新使用,因此总使用量不会超过屋顶。

于 2012-11-05T12:29:36.227 回答
8

Malloc 不必将内存返回给操作系统。类 unix 系统上的大多数 malloc 实现都不会这样做。特别是对于较小的对象尺寸。

这样做是出于性能原因。

我只是注意到这可能不清楚。“malloc”是指与 malloc 函数相关的整个子系统 - malloc、free、realloc、calloc 以及您的 libc 可能实现的任何特殊函数。

于 2012-11-05T12:29:49.037 回答
5

为了简化事情,在动态内存分配中有两个内存管理器在工作:操作系统内存管理器进程内存管理器(可能不止一个)。操作系统内存管理器将“大块”内存分配给各个进程内存管理器。每个进程内存管理器跟踪分配的段,以及“释放的段”。进程内存管理器不会将空闲的段返回给操作系统内存管理器,因为它更有效地保留它,以防它以后需要分配更多内存。

于 2012-11-05T13:43:11.280 回答