新闻中心

C++怎么实现一个简单的内存泄漏检测工具_C++重载new和delete操作符

2025-11-25
浏览次数:
返回列表
通过重载new/delete并记录分配信息,可实现内存泄漏检测,在程序结束时报告未释放内存块。

c++怎么实现一个简单的内存泄漏检测工具_c++重载new和delete操作符

在C++开发中,内存泄漏是常见问题。通过重载全局的newdelete操作符,我们可以实现一个简单的内存泄漏检测工具,记录每次内存分配与释放的信息,并在程序结束时报告未释放的内存块。

重载new和delete操作符

要实现内存检测,我们需要替换默认的newdelete行为,在分配和释放内存时插入日志记录逻辑。

以下是一个基本实现:

// MemoryTracker.h
#include <iostream>
#include <map>
#include <string>
<p>struct AllocInfo {
size_t size;
const char* file;
int line;
};</p><p>// 全局映射表,记录当前未释放的内存
extern std::map<void*, AllocInfo> g_allocations;</p><p>// 重载 new 操作符
void<em> operator new(size_t size, const char</em> file, int line);
void<em> operator new[](size_t size, const char</em> file, int line);</p><p>// 普通 new 的重载(无文件行号)
void<em> operator new(size_t size);
void</em> operator new[](size_t size);</p><p>// 重载 delete 操作符
void operator delete(void<em> ptr) noexcept;
void operator delete[](void</em> ptr) noexcept;</p><p>// 打印内存泄漏报告
void printMemoryLeaks();</p>

// MemoryTracker.cpp

#include "MemoryTracker.h"
#include <iostream>
<p>std::map<void*, AllocInfo> g_allocations;</p><p>void<em> operator new(size_t size, const char</em> file, int line) {
void* ptr = malloc(size ? size : 1); // 防止 new(0)
if (ptr) {
g_allocations[ptr] = {size, file, line};
}
return ptr;
}</p><p>void<em> operator new[](size_t size, const char</em> file, int line) {
return operator new(size, file, line);
}</p><p>void* operator new(size_t size) {
return operator new(size, "unknown", 0);
}</p><p>void* operator new[](size_t size) {
return operator new[](size, "unknown", 0);
}</p><p>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);
}</p><p>void operator delete[](void* ptr) noexcept {
operator delete(ptr);
}</p><p>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";
}
}
}</p>

使用宏简化调用

为了自动传入文件名和行号,我们可以定义宏来替换new关键字。

在项目中包含头文件后,添加如下宏定义:

#define new new(__FILE__, __LINE__)

这样所有使用new的地方都会携带位置信息。注意:这个宏会影响整个翻译单元,建议只在需要检测的源文件中局部启用。

美图云修 美图云修

商业级AI影像处理工具

美图云修 50 查看详情 美图云修

实际使用示例

下面是一个测试例子:

#include "MemoryTracker.h"
<p>// 启用带位置信息的 new</p><h1>define new new(<strong>FILE</strong>, <strong>LINE</strong>)</h1><p>int main() {
int<em> p1 = new int(42);
int</em> p2 = new int[10];</p><pre class='brush:php;toolbar:false;'>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++内存管理机制。

以上就是C++怎么实现一个简单的内存泄漏检测工具_C++重载new和delete操作符的详细内容,更多请关注其它相关文章!


# 多线程  # 西北关键词排名有必要吗  # 酒业产品营销推广方案  # 牙膏的营销推广  # 绥德抖音seo优化  # 立金哥seo  # 株洲全网网络推广seo  # seo蜘蛛推广  # 巴彦淖尔商机网站建设  # 游泳馆营销推广措施  # 洪梅网络营销推广价格  # 句柄  # 放在  # 有什么区别  # 结束时  # 工具  # 是一个  # 如何实现  # 如何使用  # 美图  # 行号  # 标准库  # c++开发  # 常见问题  # stream  # ios  # c++  # ai  #  


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 在J*a中如何使用BigDecimal进行高精度计算_BigDecimal类应用指南  Win11怎么隐藏桌面图标 Win11一键隐藏所有桌面元素及恢复显示  抖音小游戏合成大西瓜免费秒玩入口链接 抖音小游戏热门合集秒玩网站  AO3最新入口2025公告_AO3中文官网合集  Sublime Text怎么显示空格和制表符_Sublime显示不可见字符设置  谷歌邮箱网页版官方页面入口 谷歌邮箱网页端快速访问  Lar*el如何正确地在控制器和模型之间分配逻辑_Lar*el代码职责分离与架构建议  b站怎么删除评论_b站评论管理与删除操作  支付宝如何管理隐私设置_支付宝隐私保护的配置技巧  Promise错误处理:在catch后终止链式then执行的策略  Win11怎么查看电脑配置_Win11硬件配置检测工具使用  千牛数据看板网页版_千牛数据看板网页版访问方法  LocoySpider如何部署到云服务器_LocoySpider云部署的远程配置  神经网络二分类模型训练异常:高损失与完美验证准确率的排查与修正  顺丰快递查询系统 官方正版查询入口  在J*a中如何开发简易博客标签推荐系统_博客标签推荐项目实战解析  CSS Box Model与弹性按钮:维持布局稳定的动画实践  Angular响应式表单:实现提交后表单及按钮的禁用与只读化  一加手机电池耗电快怎么办_一加手机电池耗电快的解决方法  Python字典中优雅地迭代剩余元素的方法  Mac怎么使用表情符号_Mac Emoji快捷键面板  2025AO3夸克浏览器通道_AO3手机HTTPS安全入口分享  Go与Ruby之间实现AES加密互通:CFB模式下的密钥长度匹配策略  taptap防沉迷怎么解除 taptap解除健康系统限制说明【2025最新】  uc浏览器网页版入口 uc浏览器网页版最新网址  4399免费游戏网址入口 4399小游戏免费入口点开即玩  俄罗斯浏览器官网直达链接 俄罗斯浏览器最新在线入口导航  如何修改开机登录密码_Windows账户安全设置超详细教程【必学】  在J*a中如何开发在线活动报名与管理系统_活动报名管理项目实战解析  微信网页版官方快速登录入口 微信网页版网页版账号直达  小猿搜题在线学习页面在哪_小猿搜题在线学习中心入口  J*aScript中高效管理与清空动态列表:避免循环陷阱  最新韩小圈网页版登录入口_官网在线观看官方链接  c++20的std::jthread是什么_c++可中断线程与RAII式管理  必由学官网入口 必由学教师登录入口  LINUX的I/O重定向是什么_深入理解LINUX中 >、>> 与 < 的区别  优化Log4j2控制台输出性能:解决异步日志瓶颈  蓝湖怎样用切图标注提对接效率_蓝湖用切图标注提对接效率【设计对接】  Golang如何优雅处理error_Golang error处理最佳实践总结  反效果?《战地6》免费试玩开启后玩家数不升反降  Django模型中自动计算可用余额的实现方法  Pandas DataFrame 多条件优先级排序与排名  windows10怎么关闭系统提示音_windows10彻底静音设置方法  Windows10怎么开启存储感知 Windows10系统设置自动清理临时文件释放C盘空间【教程】  《噬血代码2》新预告片发布 展示游戏剧情  lar*el怎么安全地存储和获取配置文件中的敏感信息_lar*el敏感信息安全存储方法  如何在离线环境中使用Composer_Composer离线安装依赖包的技巧与策略  c++中的std::forward_list和std::list有什么不同_c++ forward_list与list区别分析  CSS如何设置hover状态颜色_hover伪类调整背景或文字颜色  如何在J*a中使用Locale处理多语言环境 

搜索