跟踪C ++内存分配

时间:2009-05-26 11:16:59

标签: c++ memory-management visualization

我正在寻找一种在C ++程序中跟踪内存分配的方法。我对对内存泄漏感兴趣,这似乎是大多数工具试图找到的内容,而是为应用程序创建内存使用情况配置文件。理想输出可以是函数名称的大列表加上随时间推移的最大分配字节数,也可以是更好的堆积随时间变化的图形表示。横轴是时间,纵轴堆空间。每个函数都会获得它自己的颜色,并根据分配的堆字节绘制线条。用于识别分配的对象类型的加分点。

我们的想法是找到内存瓶颈/可视化哪些函数/线程消耗最多的内存,并且应针对进一步优化。

我简要地看过Purify,BoundsChecker和AQTime,但它们似乎并不像我追求的那样。 Valgrind看起来很合适,但是,我在Windows上。 Memtrack看起来很有希望,但需要对源代码进行重大更改。

我的谷歌技能一定让我失望,因为它似乎不是这么罕见的要求?创建这样的工具所需的所有信息都应该可以从程序的调试符号和运行时API调用中获得 - 不是吗?

10 个答案:

答案 0 :(得分:31)

使用Valgrind及其工具Massif。它的示例输出(它的一部分):

99.48% (20,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->49.74% (10,000B) 0x804841A: main (example.c:20)
| 
->39.79% (8,000B) 0x80483C2: g (example.c:5)
| ->19.90% (4,000B) 0x80483E2: f (example.c:11)
| | ->19.90% (4,000B) 0x8048431: main (example.c:23)
| |   
| ->19.90% (4,000B) 0x8048436: main (example.c:25)
|   
->09.95% (2,000B) 0x80483DA: f (example.c:10)
  ->09.95% (2,000B) 0x8048431: main (example.c:23)

因此,您将获得详细信息:

  • WHO在上例中分配了内存(函数:g(),f()和main());您还可以获得完整的回溯,从而导致分配功能,
  • 到内存的WHICH数据结构(上例中没有数据结构),
  • 什么时候发生,
  • 所有已分配内存的百分比(g:39.7%,f:9.95%,主要:49.7%)。

这是Massif manual

您可以跟踪堆分配以及堆栈分配(默认情况下已关闭)。

<强> PS。我刚看到你在Windows上。我会留下答案,因为它给出了一个可以从一个可能的工具中得到什么的图片。

答案 1 :(得分:18)

Microsoft已经记录了很好的内存跟踪功能。但是,由于某些原因,它们在开发人员社区中并不是很有名。这些是CRT调试功能。好的起点是CRT Debug Heap functions

查看以下链接以获取更多详细信息

  1. Heap state reporting functions
  2. Tracking heap allocation requests。这可能是您正在寻找的功能。

答案 2 :(得分:13)

对于通用C ++内存跟踪器,您需要重载以下内容:

global operator new
global operator new []
global operator delete
global operator delete []
any class allocators
any in-place allocators

棘手的一点是获取有用的信息,重载的运算符只有分配器的大小信息和删除的内存指针。一个答案是使用宏。我知道。讨厌。示例 - 放置在所有源文件中包含的标题中:

#undef new

void *operator new (size_t size, char *file, int line, char *function);
// other operators

#define new new (__FILE__, __LINE__, __FUNCTION__)

并使用以下命令创建源文件:

void *operator new (size_t size, char *file, int line, char *function)
{
  // add tracking code here...
  return malloc (size);
}

以上只有在类范围内没有任何新的运算符时才有效。如果你确实有类范围,请执行:

#define NEW new (__FILE__, __LINE__, __FUNCTION__)

并将'new type'替换为'NEW type',但这可能需要更改大量代码。

由于它是一个宏,删除内存跟踪器非常简单,标题变为:

#if defined ENABLED_MEMORY_TRACKER
#undef new

void *operator new (size_t size, char *file, int line, char *function);
// other operators

#define NEW new (__FILE__, __LINE__, __FUNCTION__)
#else
#define NEW new
#endif

和实施文件:

#if defined ENABLED_MEMORY_TRACKER
void *operator new (size_t size, char *file, int line, char *function)
{
  // add tracking code here...
  return malloc (size);
}
endif

答案 3 :(得分:7)

Monitoring Your PC's Memory Usage For Game Development包含了我正在寻找的几乎完美的例子。它需要一段时间才能运行,但文章的作者非常有帮助。您可以在Memtracer找到该工具的源代码。

我在SWENG(软件工程邮件列表)上也得到了很多有用的答案。该线程被称为“[Sweng-Gamedev]监视C ++内存使用情况?”。

答案 4 :(得分:2)

更新:@ Skizz的答案

自C ++ 20起,我们可以使用std::source_location代替__FILE____LINE__之类的宏。

(因为这是一个主要的简化,所以我认为值得单独回答)。

答案 5 :(得分:1)

也请尝试这个:Memory Validator

答案 6 :(得分:0)

在Mac OS X上,您可以使用代码分析工具Shark来执行此操作,IIRC。

答案 7 :(得分:0)

在Xcode上,您可以使用Instruments跟踪分配,VM使用情况和其他一些参数。在iOS开发人员中最受欢迎,但值得一试。

答案 8 :(得分:0)

“堆随时间变化的图形表示” - 接近您要查找的内容在Intel(R) Single Event API中实现,详细信息可以在this article中找到(它相当大,可以放在这里)。 Memory block allocations over time

它显示了每个块大小分配的时间线,并允许在代码中添加额外的标记,以便更好地理解整个图片。

答案 9 :(得分:0)

Visual Studio IDE自2015年以来就具有内置的堆分析支持,这可能是最简单的开始。它具有随时间变化的堆使用情况的图形视图,并可以按功能/方法跟踪分配。

heap profiling

CRT还具有调试和配置文件支持,这更详细,更底层。您可以使用其他工具跟踪数据并绘制结果:

尤其要研究_CrtMemCheckpoint和相关功能。