监控C++中的内存分配

Monitoring Memory Allocation in The C++

本文关键字:内存 分配 C++ 监控      更新时间:2023-10-16

在源代码中监视内存分配/de_allocation的最佳方法是什么。我有一个C++程序,它动态地分配大量内存,我想跟踪哪个对象从哪个类中获取并释放内存。

我想要的程序输出是:

Creating Object from ClassA, Memory Usage ...
Creating Object from ClassB, Memory Usage ...
...
Freeing  Object from ClassA, Memory Freed ...

我现在所做的只是让全局新操作符过载,但我听说它不太安全。此外,我需要一种不需要更改所有类的方法(即使用基类,并且所有类都有一个字符串变量ClassName)。

-------------------------------------编辑---------------------------------------

1-我不想使用外部工具,需要在代码中使用。

2-如果我重载全局新运算符,我如何访问类或其他成员的名称?

看看名为应用程序验证器的MS工具,也看看VS2010探查器。

我讨厌这个跟踪内存泄漏的工具,但对于监控allocs/dellocs,它应该做你想做的事情:UMDH。

In在很大程度上取决于您是想只在开发中还是在生产中进行,以及您的性能要求是什么。对于Linux上的开发,你通常会从Valgrind的Massif开始,如果你正在寻找一个更自定义的解决方案和/或生产模式,你可以考虑将malloc/calloc/realloc重写代码(我在这里的例子)与libunfind相结合。

2-如果我重载全局新运算符,我如何访问类或其他成员的名称?

你不能。您必须明白,new和delete运算符不是直接的函数调用。实际上,类似MyClass* p = new MyClass();的语法等效于:

MyClass* p = (MyClass*) malloc(sizeof(MyClass)); // A) allocate the memory.
new(p) MyClass(); // B) call constructor (via placement-new syntax (to illustrate)).

delete p;相当于:

p->~MyClass();  // C) call destructor.
free(p);        // D) free the memory.

当您重载新的delete运算符时,编译器实际上允许您重载的只是步骤A)和D)。换句话说,当你到达自定义new操作符的主体时,对象还没有创建,因此,你不能访问或打印任何关于它的信息(类、名称等),除了它在内存中的地址,你可以在重载的new中打印它。类似地,当您到达自定义的delete操作符时,对象已经被破坏,任何试图使用内存中可能仍在悬挂的信息的行为都是未定义的行为,尤其是如果您想使用虚拟函数或字符串值。

实际上,使用这种方法所能做的最好的事情就是打印在新运算符中创建的指针,并打印由delete运算符删除的指针。

而且,正如其他人所提到的,在新的delete操作符中执行操作时,必须警惕无限递归。例如,一个简单的行,如:

std::cout << "Created pointer: " << reinterpret_cast<std::size_t>(p) << std::endl;

几乎肯定会导致许多对new和delete的调用(创建临时字符串、扩展缓冲区等)

因此,您可能必须想出一个聪明的方法来输出您想要输出的日志消息,而不会导致任何新的删除,或者您必须将新的删除运算符重载限制为仅限于框架的类。对于后者,最简单的方法是将其放在基类中。另一种选择是使用一点MACRO魔法,但这仍然会带来干扰和麻烦。

而且,在这一点上,如果你必须创建一个基类(用于你库的所有类)来处理创建-删除的日志记录(或者创建一组MACRO放在你创建的每个类中),你也可以使用构造函数/析构函数来打印这些日志消息,并保持新的删除操作符不变。

1-我不想使用外部工具,需要在代码中使用。

为什么不呢?外部工具(像Valgrind这样的虚拟机,或者通用的探查器/内存跟踪器)很可能会比你做得更好,侵入性更小。