【问题标题】:Memory usage doesn't decrease when free() used [duplicate]使用 free() 时内存使用量不会减少 [重复]
【发布时间】:2021-07-18 22:01:51
【问题描述】:

我正在编写独立于操作系统的无锁队列,到目前为止效果很好,但内存管理存在小问题。我不确定它的 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

【问题讨论】:

  • 检查内存泄漏等的更好方法是使用 Valgrind(仅限 Linux)或 Purify。

标签: c linux multithreading pthreads


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    这样做是出于性能原因。

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

    【讨论】:

    • 在 Linux 上用于更改地址空间的系统调用是 mmapmunmap(和 mprotect)。它们很昂贵,并且地址空间只能以页面大小(通常为 4Kbytes)粒度变化。 malloc+free 实现尽量重用内存。
    • @BasileStarynkevitch 您忘记了 sbrk,它也用于为进程分配更多内存。
    • 我认为最近的malloc 实现越来越少使用sbrk,特别是因为它可能不太适合线程,并且因为地址空间布局随机化。
    • @BasileStarynkevitch 在具有普通 glibc 的 Linux 上,malloc 使用 brk 从内核分配其内存,用于所有低于 128kB 的分配。用 strace 试试。
    • @Art 取决于 mallopt(M_MMAP_THRESHOLD) 中的设置,但默认为 128k。在 x64 上实际调用 malloc(使用默认值),它的 (128*1024)-23 是调用 mmap() 的第一个分配,-24 仍然调用 sbrk()。就 FEI
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 2014-02-02
      • 2020-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-02
      相关资源
      最近更新 更多