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++中重载newdelete;可以使用跟踪内存分配和使用的新函数重载基本的 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++ 中的内存分配分析的主要内容,如果未能解决你的问题,请参考以下文章

C++中内存分配问题

C# 中锯齿状数组的内存分配与 C++ 中的二维数组内存分配

小白学习C++ 教程十六C++ 中的动态内存分配

「C++」频繁分配释放内存导致的性能问题的分析

什么是 C++ 中的动态内存分配?

什么是 C++ 中的动态内存分配?