C++ 用C+跟踪内存使用情况+;并评估内存消耗

C++ 用C+跟踪内存使用情况+;并评估内存消耗,c++,memory-management,memory-leaks,C++,Memory Management,Memory Leaks,我在代码中遇到了以下问题:我使用Valgrind和gperftools执行堆检查和堆分析,以查看是否释放了分配的所有内存。这些工具的输出看起来不错,似乎我没有失去记忆。然而,当我查看top和ps的输出时,我感到困惑,因为这基本上不代表我用valgrind和gperftools观察到的结果 以下是数字: 顶级报告:RES 150M Valgrind(Massif)报告:峰值使用量23M gperftools堆分析器报告:227m峰值使用率 我现在的问题是,区别来自哪里?我还试图在Valgrin

我在代码中遇到了以下问题:我使用Valgrind和gperftools执行堆检查和堆分析,以查看是否释放了分配的所有内存。这些工具的输出看起来不错,似乎我没有失去记忆。然而,当我查看
top
ps
的输出时,我感到困惑,因为这基本上不代表我用valgrind和gperftools观察到的结果

以下是数字:

  • 顶级报告:RES 150M
  • Valgrind(Massif)报告:峰值使用量23M
  • gperftools堆分析器报告:227m峰值使用率
我现在的问题是,区别来自哪里?我还试图在Valgrind中跟踪堆栈的使用情况,但没有成功

更多详情:

  • 这个过程基本上是通过C api将数据从mysql加载到内存中
  • 加载完成后,执行泄漏检查并在短时间内断开,显示最终丢失144字节,可访问10M,这与当前分配的数量相符
  • 库不执行复杂的IPC,它启动几个线程,但只有一个线程正在执行工作
  • 它不加载其他复杂的系统库
  • /proc/pid/smaps中的PSS大小对应于TOP和ps中的RES大小

你有什么想法吗?报告的内存消耗的差异是从哪里来的?如何验证我的程序是否正常运行?您知道我如何进一步调查这个问题吗?

默认情况下,Massif只报告堆大小。TOP报告内存中的实际大小,包括程序代码本身使用的大小以及堆栈大小


尝试向Massif提供
--stacks=yes
选项,告诉它报告总内存使用量,包括堆栈空间,并查看这是否会改变图片?

根据ps/top文章报告程序在唯一运行的程序时使用的内存量。假设您的程序使用一组共享库,如STL,这些库已经加载到内存中,那么由于程序的执行而分配的实际内存量与如果它是唯一的进程,它将分配的内存量之间存在差距。

最后,我能够解决这个问题,并且会很高兴分享我的发现。一般来说,从我的角度来看,评估程序内存消耗的最佳工具是Valgrind提供的工具。它允许您分析堆消耗,并为您提供详细的分析

要分析应用程序堆,请立即运行
valgrind--tool=massif prog
,这将使您能够基本访问有关典型内存分配函数(如
malloc
和friends)的所有信息。然而,为了更深入地挖掘,我激活了选项
——pages as heap=yes
,它甚至会报告关于底层系统调用的信息。下面给出的示例是我的分析会话中的一些内容:

 67  1,284,382,720      978,575,360      978,575,360             0            0
100.00% (978,575,360B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc.
->87.28% (854,118,400B) 0x8282419: mmap (syscall-template.S:82)
| ->84.80% (829,849,600B) 0x821DF7D: _int_malloc (malloc.c:3226)
| | ->84.36% (825,507,840B) 0x821E49F: _int_memalign (malloc.c:5492)
| | | ->84.36% (825,507,840B) 0x8220591: memalign (malloc.c:3880)
| | |   ->84.36% (825,507,840B) 0x82217A7: posix_memalign (malloc.c:6315)
| | |     ->83.37% (815,792,128B) 0x4C74F9B: std::_Rb_tree_node<std::pair<std::string const, unsigned int> >* std::_Rb_tree<std::string, std::pair<std::string const, unsigned int>, std::_Select1st<std::pair<std::string const, unsigned int> >, std::less<std::string>, StrategizedAllocator<std::pair<std::string const, unsigned int>, MemalignStrategy<4096> > >::_M_create_node<std::pair<std::string, unsigned int> >(std::pair<std::string, unsigned int>&&) (MemalignStrategy.h:13)
| | |     | ->83.37% (815,792,128B) 0x4C7529F: OrderIndifferentDictionary<std::string, MemalignStrategy<4096>, StrategizedAllocator>::addValue(std::string) (stl_tree.h:961)
| | |     |   ->83.37% (815,792,128B) 0x5458DC9: var_to_string(char***, unsigned long, unsigned long, AbstractTable*) (AbstractTable.h:341)
| | |     |     ->83.37% (815,792,128B) 0x545A466: MySQLInput::load(std::shared_ptr<AbstractTable>, std::vector<std::vector<ColumnMetadata*, std::allocator<ColumnMetadata*> >*, std::allocator<std::vector<ColumnMetadata*, std::allocator<ColumnMetadata*> >*> > const*, Loader::params const&) (MySQLLoader.cpp:161)
| | |     |       ->83.37% (815,792,128B) 0x54628F2: Loader::load(Loader::params const&) (Loader.cpp:133)
| | |     |         ->83.37% (815,792,128B) 0x4F6B487: MySQLTableLoad::executePlanOperation() (MySQLTableLoad.cpp:60)
| | |     |           ->83.37% (815,792,128B) 0x4F8F8F1: _PlanOperation::execute_throws() (PlanOperation.cpp:221)
| | |     |             ->83.37% (815,792,128B) 0x4F92B08: _PlanOperation::execute() (PlanOperation.cpp:262)
| | |     |               ->83.37% (815,792,128B) 0x4F92F00: _PlanOperation::operator()() (PlanOperation.cpp:204)
| | |     |                 ->83.37% (815,792,128B) 0x656F9B0: TaskQueue::executeTask() (TaskQueue.cpp:88)
| | |     |                   ->83.37% (815,792,128B) 0x7A70AD6: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
| | |     |                     ->83.37% (815,792,128B) 0x6BAEEFA: start_thread (pthread_create.c:304)
| | |     |                       ->83.37% (815,792,128B) 0x8285F4B: clone (clone.S:112)
| | |     |                         
| | |     ->00.99% (9,715,712B) in 1+ places, all below ms_print's threshold (01.00%)
| | |     
| | ->00.44% (4,341,760B) in 1+ places, all below ms_print's threshold (01.00%)
67 1284382720 978575360 978575360 0
100.00%(978575360B)(页面分配系统调用)mmap/mremap/brk,--alloc fns等。
->87.28%(854118400B)0x8282419:mmap(syscall template.S:82)
|->84.80%(829849600B)0x821DF7D:_int_malloc(malloc.c:3226)
||->84.36%(825507840B)0x821E49F:|u int|u memalign(malloc.c:5492)
|||->84.36%(825507840B)0x8220591:memalign(malloc.c:3880)
|| |->84.36%(825507840B)0x82217A7:posix|u memalign(malloc.c:6315)
|| |->83.37%(815792128B)0x4C74F9B:std:_Rb_tree_node*std:_Rb_tree:_mu create_node(std::pair&)(MemalignStrategy.h:13)
|| | |->83.37%(815792128B)0x4C7529F:OrderIndifferentDictionary::addValue(std::string)(stl_tree.h:961)
|| | |->83.37%(815792128B)0x5458DC9:var_to_字符串(字符***,无符号长,无符号长,AbstractTable*)(AbstractTable.h:341)
|| | |->83.37%(815792128B)0x545A466:MySQLInput::load(std::shared|ptr,std::vector const*,Loader::params const&)(MySQLLoader.cpp:161)
|| | |->83.37%(815792128B)0x54628F2:Loader::load(Loader::params const&)(Loader.cpp:133)
|| | |->83.37%(815792128B)0x4F6B487:MySQLTableLoad::executePlanOperation()(MySQLTableLoad.cpp:60)
|| | |->83.37%(815792128B)0x4F8F8F1:_PlanOperation::execute_throws()(PlanOperation.cpp:221)
|| | |->83.37%(815792128B)0x4F92B08:_PlanOperation::execute()(PlanOperation.cpp:262)
|| | |->83.37%(815792128B)0x4F92F00:_PlanOperation::operator()(PlanOperation.cpp:204)
|| | |->83.37%(815792128B)0x656F9B0:TaskQueue::executeTask()(TaskQueue.cpp:88)
|| | |->83.37%(815792128B)0x7A70AD6:???(在/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16中)
|| | |->83.37%(815792128B)0x6BAEEFA:start_线程(pthread_create.c:304)
|| |->83.37%(815792128B)0x8285F4B:clone(clone.S:112)
| | |     |                         
|| |->00.99%(9715712b),在1+个位置,均低于ms|U print的阈值(01.00%)
| | |     
||->00.44%(4341760B),在1+个位置,均低于ms_print的阈值(01.00%)
正如您所看到的,我的内存分配中约85%来自单个分支,现在的问题是,如果原始堆分析显示内存消耗正常,那么为什么内存消耗如此之高。如果你看看这个例子,你就会明白为什么。对于分配,我使用了
posix_memalign
来确保分配发生在有用的边界上。然后将该分配器从外部类传递到内部成员变量(本例中为映射),以使用分配器进行堆分配。然而,在我的例子中,我选择的边界太大了——4096。这意味着,您将分配4b