c++ - 停止通过 STL 容器调用重载的 new 和 delete 运算符

标签 c++ memory-management operator-overloading instrumentation

我正在开发内存泄漏工具。在这里,我重载了新的和删除的运算符。它工作正常。但是我为其创建此工具的代码大约有 15000 行。我无法更改现有代码,只能将 memoryleak 工具函数调用到现有代码中。具有 STL 容器(如列表、 map 、堆栈等)的现有代码。 STL 容器还调用 new 和 delete 运算符来分配或释放内存。我希望 STL 容器应该调用 new 和 delete 运算符,它们不在重载的 new 和 delete 中。 例如:

int *iptr = new int[10] ----> should call overloaded new[]
delete [] iptr -------------> should call overloaded delete[]
map.insert(10) -------------> should call default new[] ( which are in new.h)
map.erase()  ---------------> should call default delete[] ( which are in new.h)

我该怎么做? 我们将不胜感激。

抱歉,我忘了说我正在用以下宏替换 new 和 delete:

#define new DEBUG_NEW
#define DEBUG_NEW TrackMemory(__FILE__, __LINE__) ->* new
#define delete TrackDelete(__FILE__, __LINE__); delete

这里TrackMemory是用来跟踪内存的,new是用来分配内存的,和delete一样。 我的工具也能正常工作,但是当 STL 容器出现时,它会给出错误的结果,因为它们只使用重载的新容器。 请帮帮我

最佳答案

从编写这些“空”函数开始。它们将由您自己替换标准的新建和删除:

void *operator new (size_t memorySize);
void *operator new[] (size_t memorySize);
void *operator new (size_t memorySize, const std::nothrow_t &) throw ();
void *operator new[] (size_t memorySize, const std::nothrow_t &) throw ();
void operator delete (void *memoryPointer);
void operator delete[] (void *memoryPointer);
void operator delete (void *memoryPointer, const std::nothrow_t &) throw ();
void operator delete[] (void *memoryPointer, const std::nothrow_t &) throw ();

然后编写单独的函数来分配和释放内存:

void *myNew (size-t memorySize);
void myDelete (void *memoryPointer);

在开头提到的函数中调用你的 myNew 和 myDelete。

使用 HeapAlloc 和 HeapFree 实现 myNew 和 myDelete。

然后制作一个全局变量并像这样标记它(这是 Visual Studio):

#pragma init_seg(lib)

这将确保您的全局变量首先初始化,最后清理。

到目前为止,我们已经涵盖了基础。要获得真正的泄漏报告功能,您需要在 myNew 函数中存储有关已分配内存的信息。

使用全局变量的析构函数来报告所有泄漏。

此外,您可以使用 StackWalk 获取调用堆栈并将其存储在每次内存分配中。

有些人可能想知道为什么要这样做而不是使用其他工具:

  • 根据我的经验,Visual Studio 中的泄漏报告是有限的。它不显示调用堆栈,只显示直接调用者,这使它变得毫无意义。
  • 一些工具使用#define 来替换 new、delete、alloc、...,但这在很多情况下会产生问题(例如,一个类方法被称为 free(在 Qt 中看到这个),或者删除完成在 header 中,但在必须链接的 .lib 中是新的(也在 Qt 中看到))。
  • 其他工具需要您制作应用程序的交互式快照,然后再进行比较。在我上面的方法中,您会获得自动泄漏报告(无需手动操作,始终在应用程序结束时,...)。

一旦有了自己的内存管理器,就可以开始考虑添加其他功能(例如,基于调用堆栈的内存统计信息、查找内存覆盖的技巧、查找删除后重用内存的代码的技巧,.. .).

关于c++ - 停止通过 STL 容器调用重载的 new 和 delete 运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4944852/

相关文章:

c++ - 在第 5 版中开发自定义列表控件

c - 增加内存地址如何影响指针

iphone - 如何释放为 appDelegate 共享实例分配的内存

c++ - 错误 C2679 : binary '==' : no operator found which takes a right-hand operand of type

c++ - 调用模板化成员函数与模板化全局函数在通用工厂中创建对象

c++ - 你如何使用 range-v3 范围制作像 ranges::to<T>() 这样的可管道函数?

c++ - std::filesystem::path 和 std::string 之间的隐式转换,应该发生吗?

c++ - 存储在 vector 中的对象的所有权

f# - 非惯用的全局运算符重载如何工作?

c++ - map 键没有可行的重载 '=' 错误