通过重载new/delete并记录分配信息,可实现内存泄漏检测,在程序结束时报告未释放内存块。

在C++开发中,内存泄漏是常见问题。通过重载全局的new和delete操作符,我们可以实现一个简单的内存泄漏检测工具,记录每次内存分配与释放的信息,并在程序结束时报告未释放的内存块。
重载new和delete操作符
要实现内存检测,我们需要替换默认的new和delete行为,在分配和释放内存时插入日志记录逻辑。
以下是一个基本实现:
// MemoryTracker.h#include#include
// MemoryTracker.cpp
立即学习“C++免费学习笔记(深入)”;
#include "MemoryTracker.h" #includestd::map
g_allocations; void operator new(size_t size, const char file, int line) { void* ptr = malloc(size ? size : 1); // 防止 new(0) if (ptr) { g_allocations[ptr] = {size, file, line}; } return ptr; }
void operator new[](size_t size, const char file, int line) { return operator new(size, file, line); }
void* operator new(size_t size) { return operator new(size, "unknown", 0); }
void* operator new[](size_t size) { return operator new[](size, "unknown", 0); }
void operator delete(void* ptr) noexcept { if (ptr == nullptr) return; auto it = g_allocations.find(ptr); if (it != g_allocations.end()) { g_allocations.erase(it); } free(ptr); }
void operator delete[](void* ptr) noexcept { operator delete(ptr); }
void printMemoryLeaks() { if (g_allocations.empty()) { std::cout << "No memory leaks detected.\n"; } else { std::cout << "Memory leaks detected:\n"; for (const auto& pair : g_allocations) { std::cout << "Address: " << pair.first << " Size: " << pair.second.size << " File: " << pair.second.file << " Line: " << pair.second.line << "\n"; } } }
使用宏简化调用
为了自动传入文件名和行号,我们可以定义宏来替换new关键字。
在项目中包含头文件后,添加如下宏定义:
#define new new(__FILE__, __LINE__)
这样所有使用new的地方都会携带位置信息。注意:这个宏会影响整个翻译单元,建议只在需要检测的源文件中局部启用。
实际使用示例
下面是一个测试例子:
#include "MemoryTracker.h"// 启用带位置信息的 new
define new new(FILE, LINE)
int main() { int p1 = new int(42); int p2 = new int[10];
delete[] p2; // 正确释放 // delete p1; // 故意遗漏,制造泄漏 printMemoryLeaks(); // 程序退出前调用 return 0;}
运行结果会显示类似:
Memory leaks detected: Address: 0x7fb1c8c00000 Size: 4 File: main.cpp Line: 7注意事项与限制
这种简单检测工具有几个要点需要注意:
- 必须确保
printMemoryLeaks()在程序退出前被调用,最好放在main函数末尾或使用atexit()注册 - 宏
#define new可能影响标准库或其他第三方代码,应谨慎使用范围 - 不支持placement new等高级用法
- 多线程环境下需要加锁保护
g_allocations - 无法检测堆栈对象或资源泄漏(如文件句柄)
基本上就这些。这个轻量级方案适合学习和小型项目。对于生产环境,推荐使用Valgrind、AddressSanitizer等专业工具。不过自己动手实现一遍,有助于深入理解C++内存管理机制。








