0

0

c++如何检测内存泄漏_c++ valgrind使用简介【工具】

冰火之心

冰火之心

发布时间:2026-01-25 13:32:02

|

401人浏览过

|

来源于php中文网

原创

Valgrind 能直接用于 C++ 程序,是 Linux 下最可靠的运行时内存泄漏检测工具之一;它通过动态二进制插桩监控 malloc/new/delete/free 匹配,要求程序用 -g 编译且避免高优化,重点关注 definitely lost 泄漏。

c++如何检测内存泄漏_c++ valgrind使用简介【工具】

Valgrind 能不能直接用于 C++ 程序

能,而且是 Linux 下最可靠的运行时内存泄漏检测工具之一。它不依赖编译器插桩(比如 ASan),而是通过动态二进制插桩在程序执行过程中监控每一块 mallocnewdeletefree 的匹配情况。只要你的 C++ 程序没用到 Valgrind 明确不支持的特性(如某些内核模块、自修改代码、部分 SIMD 指令),它就能工作。

注意:Valgrind 本身不区分 C 和 C++ 内存操作——它只认底层分配器调用。所以 newdelete 是否被正确配对,取决于它们是否最终调用了 malloc/free(标准实现下是的),但如果你重载了全局 operator new 却没调用 malloc,Valgrind 就可能漏报。

怎么用 valgrind 检测 C++ 内存泄漏

核心命令是:valgrind --leak-check=full --show-leak-kinds=all ./your_program

  • --leak-check=full:启用详细泄漏分析(不只是“有泄漏”,还显示调用
  • --show-leak-kinds=all:报告 definitely lostindirectly lostpossibly loststill reachable 四类(默认只报前两类)
  • 务必用 -g 编译你的程序(例如 g++ -g -O0 main.cpp),否则堆栈信息全是 ??
  • 避免加 -O2 或更高优化等级,部分内联或变量生命周期优化会让泄漏定位失真

示例输出中重点关注 definitely lost 行——这是最明确的泄漏:指针已丢失且内存未释放。比如:

立即学习C++免费学习笔记(深入)”;

==12345== 8 bytes in 1 blocks are definitely lost in loss record 1 of 2
==12345==    at 0x483B7F3: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12345==    by 0x1091A8: operator new(unsigned long) (in ./test)
==12345==    by 0x1091E2: main (main.cpp:5)

常见误判和干扰项怎么识别

Valgrind 报的 still reachable 不是泄漏,只是程序退出前仍有指针可访问这些内存(比如全局 std::string 缓存、单例对象内部缓存)。这类通常不用处理。

Originality AI
Originality AI

专门为网络出版商设计的抄袭和AI检测工具

下载

真正要警惕的是:

  • definitely lost:指针作用域结束且无副本,内存未 delete → 必须修复
  • indirectly lost:因为某个 definitely lost 块持有其指针,导致连带泄漏 → 先修根因
  • possibly lost:Valgrind 发现指针可能被计算地址覆盖(如数组越界写、指针算术错误),不一定真泄漏,但大概率是 bug

另外:C++ 标准库容器(如 std::vectorstd::map)内部管理的内存,只要容器析构正常,Valgrind 不会报泄漏;但如果容器里存了裸指针且没手动 delete,就会报。

为什么 valgrind 有时找不到 new/delete 不匹配

根本原因不是 Valgrind 失效,而是你没让它看到完整的生命周期:

  • 程序提前 exit() 或收到 SIGKILL:Valgrind 来不及做退出检查 → 改用 return 正常退出
  • 使用了自定义分配器(如 boost::pool)且未适配 Valgrind:它只监控 libc 分配器,默认不跟踪池式分配 → 需配合 VALGRIND_MALLOCLIKE_BLOCK 宏手动标注
  • 多线程中 delete 发生在线程销毁后:主线程退出时子线程还在跑,Valgrind 可能已终止监控 → 加 --tool=helgrind 或确保所有线程 join 完再退出
  • 静态对象析构顺序问题:全局对象 A 在 B 之前析构,而 A 的析构函数里访问了已被 B 析构的资源 → 这类泄漏 Valgrind 会报,但调用栈可能指向 __libc_start_main,需结合 --track-origins=yes 追溯初始化源头

真实项目里,Valgrind 最容易漏掉的是“跨 DLL/SO 边界的 new-delete 不匹配”(比如在 libA 中 new,在 libB 中 delete),因为不同模块可能链接不同版本的 libstdc++,导致分配器不一致——这种问题 Valgrind 无法识别语义,只能靠统一链接策略规避。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

381

2023.08.02

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

394

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

574

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

394

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

574

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

482

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

143

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

5

2026.01.21

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

41

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.7万人学习

Git 教程
Git 教程

共21课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号