如何在Linux下用Valgrind分析c++内存泄漏? (Memcheck工具)
技术百科
穿越時空
发布时间:2026-01-20
浏览: 次 编译需加-g且禁用优化:g++ -g -O0确保调试信息完整、执行流清晰;Valgrind须用--leak-check=full --show-leak-kinds=all --track-origins=yes定位泄漏;definitely lost必须修复,still reachable通常非bug;避免exit()绕过析构,慎用shared_ptr防循环引用。
编译时必须加 -g 且禁用优化
Valgrind 依赖调试信息定位泄漏源头,不加 -g 会导致报告里只有 ???,完全无法回溯到源码行。同时,-O2 或更高优化等级会让变量生命周期、内联、寄存器分配失真,造成误报(如把未初始化值当泄漏)或漏报(如提前释放被优化掉)。实操建议:
- 用
g++ -g -O0 -o myapp myapp.cpp编译,确保符号完整、执行流清晰 - 若项目用 CMake,加
set(CMAKE_BUILD_TYPE Debug)并确认CMAKE_CXX_FLAGS_DEBUG包含-g -O0 - 避免链接 strip 后的库;第三方库也尽量用带调试符号的版本(如 Ubuntu 的
*-dbg包)
运行 Valgrind 时启用完整内存检查参数
默认 valgrind ./myapp 只做基础错误检测,对内存泄漏需显式开启 --leak-check=full 并配合其他关键选项。常见遗漏点:
-
--leak-check=full:显示每块泄漏内存的分配栈,缺它就只告诉你“有泄漏”,不告诉你在哪 -
--show-leak-kinds=all:覆盖definitely lost、indirectly lost、possibly lost、still reachable四类,尤其possibly lost常被忽略但可能指向悬空指针或边界越界 -
--track-origins=yes:对Use of uninitialised value类错误,能追溯未初始化内存的来源(代价是慢 2–3 倍,但值得) - 完整命令示例:
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=valgrind-out.txt ./myapp
区分 definitely lost 和 still reachable 的真实含义
Valgrind 报告里的分类直接决定修复优先级,但很多人误判:
-
definitely lost:指针已丢失(比如局部指针变量出作用域,且无其他引用),内存彻底不可达 → 必须修复 -
still reachable:程序退出时仍有指针指向该内存(如全局std::vector缓存、单例对象成员),通常不是 bug,但若量大或持续增长,说明资源未按需释放 -
indirectly lost:父块泄漏导致子指针失效,先修父块即可,不用单独处理 - 注意:C++ 中
std::s、
tring
std::vector等容器内部 new 的内存,若容器本身是栈对象且未 move/转移,其析构会自动释放,不会报 leak —— 所以泄漏基本来自裸new未配delete,或new[]配了delete
处理 C++ RAII 与第三方库干扰
Valgrind 本身不理解 C++ 析构语义,某些 RAII 模式或库(如 Boost、Qt)会在主函数结束后才释放资源,造成假阳性。应对方式:
- 在程序末尾主动调用清理逻辑,例如 Qt 中加
QApplication::processEvents(); qApp->quit();,再等几毫秒 - 用
--suppressions=mysupp.supp屏蔽已知良性泄漏,例如 GLIBC 的__libc_freeres调用前的缓存(生成模板见valgrind --gen-suppressions=all) - 避免在
main()返回前用exit()—— 它绕过栈展开和析构,会让所有 RAII 失效,把本可自动释放的内存变成definitely lost - 若用
shared_ptr却仍泄漏,检查是否形成循环引用(如父子对象互相持shared_ptr),此时应改用weak_ptr打断环
delete 或多写了一个 std::move 的地方——这时候 --num-callers=20 和日志文件里搜索 at 0x 对应的源码行,比任何技巧都管用。
# ai
# 会在
# 很多人
# 写了
# 告诉你
# 是从
# 会让
# 第三方
# 可达
# app
# 工具
# linux
# ubuntu
# 循环
# 对象
# c++
# String
# 指针
# 栈
# red
# delete
# bug
# 作用域
# 空指针
# 仍有
# 会报
# qt
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- 如何在 ACF 中正确更新嵌套多层的 Group
- php怎么下载安装后无法解析php文件_服务器配置
- Win10如何卸载自带Edge_Win10彻底卸载
- 如何在 Go 中创建包含 map 的 slice(
- php怎么下载安装后设置默认字符集_utf8配置步
- c++如何利用doxygen生成开发文档_c++
- Win11怎么设置任务栏透明_Windows11使
- 怎么将XML数据可视化 D3.js加载XML
- Win11怎么关闭透明效果_Windows11辅助
- Python字符串操作教程_切片拼接与格式化详解
- Python与OpenAI接口集成实战_生成式AI
- Mac怎么设置登录项_Mac管理开机自启动程序【教
- 如何使用Golang实现容器安全扫描_Golang
- Win10怎样卸载DockerDesktop_Wi
- Mac的“调度中心”与“空间”怎么用_Mac多桌面
- Win11怎么设置默认终端应用_Windows11
- Win11文件扩展名怎么显示_Win11查看文件后
- 如何使用Golang benchmark测量函数延
- Python正则表达式实战_模式匹配说明【教程】
- windows如何修改文件默认打开方式_windo
- 如何优化Golang Web性能_Golang H
- XSLT怎么生成动态的HTML属性名和标签名
- 如何使用Golang encoding/json解
- TestNG的testng.xml配置文件怎么写
- 如何使用Golang sort排序切片_Golan
- Win11怎么开启远程桌面连接_Windows11
- Win11怎样安装网易云音乐_Win11安装网易云
- Win11怎么制作U盘启动盘_Win11原版系统安
- Mac系统更新下载慢或失败怎么办_解决macOS升
- Windows如何设置登录时的欢迎屏幕背景?(锁屏
- Python爬虫项目实战教程_Scrapy抓取与存
- Win10如何关闭安全中心所有通知 Win10禁用
- Windows10如何查看保存的WiFi密码_Wi
- Win11怎么设置鼠标宏_Win11鼠标按键自定义
- Drupal 中渲染节点时出现 HTML 标签嵌套
- 如何使用Golang defer优化性能_减少不必
- c++怎么处理多线程死锁_c++ lock_gua
- windows如何测试网速_windows系统网络
- php485函数执行慢怎么优化_php485性能提
- 如何在Golang中实现微服务服务拆分_Golan
- c++怎么实现高并发下的无锁队列_c++ std:
- php报错怎么查看_定位PHP致命错误与警告的方法
- c++如何使用std::bitset进行位图算法_
- Python对象比较排序规则_集合使用说明【指导】
- Windows10系统怎么查看设备管理器_Win1
- Mac如何整理桌面文件_Mac使用堆栈功能一键整理
- Python与MongoDB NoSQL开发实战_
- Win11如何更新显卡驱动 Win11检查和安装设
- mac怎么安装pip_MAC Python pip
- 如何在Golang中写入XML文件_生成符合规范的


QQ客服