C++ 中的内存分配分析
Posted
技术标签:
【中文标题】C++ 中的内存分配分析【英文标题】:Memory Allocation Profiling in C++ 【发布时间】:2009-03-31 05:16:25 【问题描述】:我正在编写一个应用程序,并且惊讶地发现它的总内存使用量已经太高了。我想分析我的应用程序的动态内存使用情况:堆中有多少种对象,哪些函数创建了这些对象?另外,每个对象使用了多少内存?
有没有简单的方法来做到这一点?我在 linux 和 windows 上工作,所以任何平台的工具都足够了。
注意:我不关心这里的内存泄漏。
【问题讨论】:
【参考方案1】:你试过Valgrind吗?它是用于 Linux 的分析工具。它有一个名为 Memcheck 的内存检查器(用于内存泄漏和其他内存问题),但它还有一个名为 Massif 的堆分析器。
【讨论】:
Valgrind 甚至还有 Eclipse 集成 (wiki.eclipse.org/index.php/Linux_Distributions_Project) 不错的提示,我不知道那个项目。我通常使用 Cmake,所以使用该工具:vtk.org/Wiki/Eclipse_CDT4_Generator 我可以将我所有的 C++ 开发移动到 Linux 中的 Eclipse CDT,谢谢。 有没有办法使用 valgrind massif 来分析对象计数和每种对象类型使用的总内存?【参考方案2】:对于简单的统计,只是为了找出所有内存的使用情况,您可以添加这样的模板:
template<class T>
class Stats
static int instance_count;
public:
Stats()
instance_count++;
~Stats()
instance_count--;
static void print()
std::cout << instance_count << " instances of " << typeid(T).name() <<
", " << sizeof(T) << " bytes each." << std::endl;
;
template<class T>
int Stats<T>::instance_count = 0;
然后你可以把它作为基类添加到你怀疑有很多实例的类中,并打印出当前内存使用的统计信息:
class A : Stats<A>
;
void print_stats()
Stats<A>::print();
Stats<B>::print();
...
这并没有向您显示对象在哪些函数中被分配,也没有提供太多细节,但它可能足以找到浪费内存的位置。
【讨论】:
如果您这样做,请记住这不是线程安全的。您可以使用std::atomic
(如果您有 C++11)或 boost::atomic
进行增量/减量。【参考方案3】:
对于 Windows,请检查“crtdbg.h”中的函数。 crtdbg.h 包含内存分配函数的调试版本。它还包含检测内存泄漏、损坏、检查堆指针的有效性等功能。
我认为以下功能会对您有用。
_CrtMemDumpStatistics _CrtMemDumpAllObjectsSince
以下 MSDN 链接列出了堆状态报告函数和示例代码 http://msdn.microsoft.com/en-us/library/wc28wkas(VS.80).aspx
【讨论】:
那个链接失效了,可能是msdn.microsoft.com/en-us/library/aa269809(v=vs.60).aspx或者msdn.microsoft.com/en-us/library/974tc9t1.aspx?【参考方案4】:你可以试试http://www.softwareverify.com/cpp/memory/index.html的内存验证器
这是我遇到的用于分析内存使用情况的最佳工具之一。 30 天评估版可供免费下载。
【讨论】:
它支持 Linux 吗?【参考方案5】:MTuner - 免费的 C/C++ 内存分析器。说明如下:
MTuner 是一个多平台内存分析、泄漏检测和分析工具,支持 MSVC、GCC 和 Clang 编译器。功能包括:基于时间轴的内存活动历史、强大的过滤、带有完整源代码的手动检测 SDK、通过命令行使用的持续集成支持、内存泄漏检测等等。使用 GCC 或 Clang 交叉编译器分析任何面向软件的平台。内置对 Windows、PlayStation 4 和 PlayStation 3 平台的支持以及基于 Windows 的交叉编译器所针对的平台。
【讨论】:
如何提交错误报告?我试过 Mtuner,它在启动带有长命令行的可执行文件时崩溃。有 github 仓库吗? 在尝试加载大的.MTuner
文件 (~9Gb) 时也会崩溃。您是否尝试一次将整个文件加载到内存中?您是否检查代码上的内存分配失败?
没有 github repo,它是闭源的。请随时向我发送有关这些崩溃的更多信息,我会修复它们/看看。
如何联系您?【参考方案6】:
您可以做几件事。最简单的就是链接一个调试malloc库;有许多可用,具体取决于您的环境的详细信息(例如,google 用于 Windows 的 _malloc_dbg。)
第二种选择是可以在C++中重载new和delete;可以使用跟踪内存分配和使用的新函数重载基本的 new 和 delete。
【讨论】:
【参考方案7】:试试gperftools - 它可以:
一次性分析代码的特定部分或整个程序。 通过可视化有向图表示数据,显示确切的函数调用及其继承。 专注于可视化图表中的特定代码区域。 显示转储之间的差异。 显示分配的空间而不是使用的空间 - 所有这些都是通过同一个转储完成的。而且,它几乎不影响程序效率。
【讨论】:
更新:gperftools 的新链接现在是:github.com/gperftools/gperftools【参考方案8】:我刚刚发布了一个 win32 本机内存分析器 MemPro,作为免费测试版。 http://www.puredevsoftware.com/MemPro.htm。它连接到 new/delete 并将数据发送到外部应用程序,您可以在其中以各种不同的方式查看分配。希望对您有所帮助。
【讨论】:
【参考方案9】:在之前的工作中,我们使用了一个名为“Purify”的工具。它是由 Rational/IBM 制造的产品。我不认为这是一个免费工具,但我记得它非常好。以下是一些信息:
http://en.wikipedia.org/wiki/IBM_Rational_Purify
【讨论】:
Purify 告诉您内存损坏和泄漏,而不是分配对象的大小【参考方案10】:Game Programming Gems Volume 2 (Amazon link) 的第 1.10 章详细介绍了 Peter Dalton 的一个简单但有效的插入式调试内存管理器,它在您转储日志时提供了一组不错的统计信息。
【讨论】:
【参考方案11】:来自Game Programming Gems Volume 8(Safari Book 预览链接)的第 4.6 章详细介绍了 Ricky Lung 的高级内存分析器,它可以以分层调用堆栈方式显示分配统计信息,但支持多线程。
【讨论】:
章节不是立即可见的,你有没有强制订阅按钮或免费试用的真实预览链接? 链接失效【参考方案12】:刚刚在AQtime site 上看到他们对“分配分析”有很好的支持。
【讨论】:
以上是关于C++ 中的内存分配分析的主要内容,如果未能解决你的问题,请参考以下文章