c++ - 释放后似乎未由较低级别的分配例程释放内存

标签 c++ memory-management memory-leaks valgrind massif

我正在调试一个复杂的 C++ 应用程序,数万行,许多嵌套对象(我这么说是因为它可能与内存碎片有关),它也是 OMP/MPI 并行化的(尽管在这里运行单节点).

基本循环遍历问题的 block ,在每个 block 上它循环遍历所有相关对象并执行某些操作。这些对象通过可变成员在内部缓存中间结果。最后 deCache 例程被调用,所有这些中间结果都应该被清除,我们进入下一个 block 。问题是在这一步似乎没有释放内存,程序在几个 block 后用完了内存。

我通过调试器运行 valgrind,并在 block 处理结束时发布了详细的 snapshop,就在解码之前和解码之后。这显示堆上的内存消耗从 23Gb 增加到 820Mb,正如预期的那样:

  --------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
  0 12,019,170,891,847   23,406,329,728   23,015,422,037   390,907,691            0
98.33% (23,015,422,037B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->44.49% (10,414,094,336B) 0x771D63: FTCinvdCdp::FTCinvdCdp(FTCinvdCdp const&) (new_allocator.h:104)
    | ->37.49% (8,774,281,216B) 0x5B6F4E: FTCinvdCdpZ::clone() const (stl_construct.h:75
...

也掉了

    -----------------------------------------------------------------------------
          n        time(i)         total(B)   useful-heap(B) extra-heap(B)        stacks(B)
    --------------------------------------------------------------------------------
      0 12,020,946,295,906      857,944,344      830,426,901    27,517,443            0
    96.79% (830,426,901B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
    ->21.15% (181,458,432B) 0x712267: void std::vector<GTHSpecSampFunc, std::allocator<GTHSpecSampFunc> >::_M_emplace_back_aux<GTHSpecSampFunc>(GTHSpecSampFunc&&) (new_allocator.h:104)
    ...

这些数字完全在我的预期之内。问题是顶部下方显示的内存几乎没有减少(实际上它会在一段时间后耗尽内存)。使用 --stacks-as-heap 运行 massif,它确实表明内存并未实际释放:

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
  0 12,286,840,539,442   24,112,730,112   24,112,730,112             0            0
100.00% (24,112,730,112B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc.
->99.54% (24,000,663,552B) 0x84392D9: mmap (in /lib64/libc-2.12.so)
| ->54.83% (13,220,446,208B) 0x83CB2DF: new_heap (in /lib64/libc-2.12.so)
| | ->53.44% (12,884,901,888B) 0x83CDB19: _int_malloc (in /lib64/libc-2.12.so)
| | | ->53.44% (12,884,901,888B) 0x83CE6AF: malloc (in /lib64/libc-2.12.so)
| | |   ->53.44% (12,884,901,888B) 0x7C74806: operator new(unsigned long) (new_op.cc:49)
| | |     ->28.94% (6,979,321,856B) 0x771D13: FTCinvdCdp::FTCinvdCdp(FTCinvdCdp const&) (new_allocator.h:104)
...

勉强变成

    --------------------------------------------------------------------------------
      n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
    --------------------------------------------------------------------------------
      0 12,292,664,324,363   23,777,185,792   23,777,185,792             0            0
    100.00% (23,777,185,792B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc.
    ->99.53% (23,665,119,232B) 0x84392D9: mmap (in /lib64/libc-2.12.so)
    | ->54.47% (12,952,010,752B) 0x83CB2DF: new_heap (in /lib64/libc-2.12.so)
    | | ->53.06% (12,616,466,432B) 0x83CDB19: _int_malloc (in /lib64/libc-2.12.so)
    | | | ->53.06% (12,616,466,432B) 0x83CE6AF: malloc (in /lib64/libc-2.12.so)
    | | |   ->53.06% (12,616,466,432B) 0x7C74806: operator new(unsigned long) (new_op.cc:49)
    | | |     ->28.22% (6,710,886,400B) 0x771D13: FTCinvdCdp::FTCinvdCdp(FTCinvdCdp const&) (new_allocator.h:104)
    | | |     | ->24.84% (5,905,580,032B) 0x5B6EFE: FTCinvdCdpZ::clone() const (stl_construct.h:75)
    | 
...

我很确定我们正确地解除了所有 vector 的分配(通过空 vector 进行交换)并且没有经典的内存泄漏(即非常一致地使用自动指针等),此外我希望这些在 vanilla 下显示(即不是页面堆)运行。

知道会发生什么吗?什么样的错误只显示在页堆运行中?有没有可能是内存碎片问题?如何解决这个问题?

最佳答案

这在具有虚拟内存的系统中很典型。底层的“内存分配”例程(“brk”)实际上只是增加了地址空间的大小。虚拟内存系统在您的进程需要时提供实际内存页面,并在其他进程需要时将它们窃取回来。因此,没有太多理由重新调整内存空间的末尾,因为它几乎只是一个数字。

关于c++ - 释放后似乎未由较低级别的分配例程释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34576603/

相关文章:

c - 由于 malloc 导致地址越界和内存泄漏

c++ - 指向 void 的指针变成智能指针

java - 在 recyclerview 中滚动时内存使用量增加

c# - Unity - Android,C# - C++ 内存泄漏

c++ - 构建非循环依赖的最简单、最有效的数据结构是什么?

c++ - 在 C++ 头文件中声明变量

c++ - 反射完美转发和访问者模式

c++ - 关于 C++ 中自动变量效率大小的实际限制是什么?

delphi - 如何通过DataSnap发送/接收TObjectList解决内存泄漏?

c++ - 如果满足条件或发生错误