讲师中心 微信公众号
AI工具推荐 视频效率加速

c++如何使用AddressSanitizer (ASan) 快速定位内存泄漏? (编译选项详解)

冬枫大大_8213

冬枫大大_8213

发布时间:2026-01-09 14:47:02

|

1035人浏览过

|

来源于php中文网

原创

AddressSanitizer 默认不检测内存泄漏,需显式启用LeakSanitizer:编译加-fsanitize=address,leak、运行前设ASAN_OPTIONS=detect_leaks=1,且程序须正常退出才能触发报告。

c++如何使用addresssanitizer (asan) 快速定位内存泄漏? (编译选项详解)

AddressSanitizer 本身不检测内存泄漏,ASan 默认只捕获越界访问、Use-After-Free、栈缓冲区溢出等**运行时内存错误**;要查内存泄漏,必须显式启用其泄漏检测器(LeakSanitizer),且需满足特定编译和运行条件。

如何开启 LeakSanitizer(LSan)并确保它真正生效

仅加 -fsanitize=address 不够——LSan 是 ASan 的配套组件,但默认可能被禁用或静默跳过。关键在三处:

  • 编译时必须同时指定 -fsanitize=address,leak(注意逗号分隔,不能只写 address)
  • 链接时不能带 -shared 或静态链接 libc(如 -static-libgcc -static-libstdc++),否则 LSan 初始化失败,日志里会显示 LeakSanitizer disabled
  • 运行前需设置环境变量:export ASAN_OPTIONS=detect_leaks=1(Linux/macOS);若未设,即使编译含 leak,LSan 也不触发

典型编译命令:

g++ -fsanitize=address,leak -g -O0 main.cpp -o main

运行前执行:export ASAN_OPTIONS=detect_leaks=1,再运行 ./main。

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

为什么程序退出后没输出泄漏报告?常见静默失败原因

LSan 只在进程正常退出(return 或 exit())时扫描堆,以下情况会导致“无报告”假象:

Obsidian (Linux)
Obsidian (Linux)

操作 Obsidian 库(纯 Markdown 笔记),并通过 notesmd-cli 实现自动化。

下载
  • 程序因信号崩溃(如 SEGFAULT)——ASan 会报错,但 LSan 不运行
  • 主线程调用 pthread_exit() 而非 return —— 进程未完全终止,LSan 不触发
  • 使用了 atexit() 注册的清理函数中又分配内存——干扰 LSan 扫描逻辑,可能跳过报告
  • 程序中调用了 _exit() 或 abort() —— 绕过正常退出流程,LSan 无机会运行

验证是否真启用:运行前加 export ASAN_OPTIONS=detect_leaks=1:log_path=asan.log,检查 asan.log.* 文件是否存在泄漏摘要行(含 LEAK SUMMARY)。

clang vs gcc 对 LSan 的支持差异与陷阱

Clang 原生集成 LSan,行为稳定;GCC 从 4.9+ 支持,但有关键限制:

  • GCC 10 及更早版本中,-fsanitize=leak 单独使用无效,必须与 address 联用(即 -fsanitize=address,leak)
  • 某些旧版 GCC(如 7.5)在启用 leak 时若链接了 libstdc++.so 的 debug 版本,可能触发符号冲突导致启动失败
  • Clang 编译的二进制可直接用 ASAN_OPTIONS 控制 LSan 行为;GCC 编译的则对 abort_on_error 等选项响应较弱

稳妥做法:优先用 Clang 12+,或确认 GCC 版本 ≥ 11,并避免混用 debug/release 标准库。

泄漏报告看不懂?关键字段解读与过滤技巧

LSan 报告中真正有用的不是堆栈顶层,而是:

  • Direct leak:代码中 new/malloc 分配后未 delete/free
  • Indirect leak:指向已泄漏内存的指针也被泄漏(通常可忽略,先修 direct)
  • 堆栈末尾的 operator new 或 malloc 行号才是泄漏点,不是上层调用者
  • 若堆栈只有 __libc_start_main 和 main,说明泄漏发生在全局对象构造或 main 开头,检查静态变量/单例初始化

快速定位:用 grep -A 10 "0x[0-9a-f]* is located" asan.log 提取地址上下文,再结合 addr2line -e main -f -C 0x... 反查源码行。

LSan 不是万能的——它无法发现循环引用导致的智能指针泄漏(如 std::shared_ptr 成环),也不跟踪未释放的文件描述符或 mmap 区域;真要覆盖全面,得配合 valgrind --tool=memcheck 或 Dr. Memory。但对裸指针和传统 C 风格内存管理,开对参数的 LSan 就是最轻量、最快的起点。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

相关专题

更多
C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

379

2026.04.23

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

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

6107

2023.07.18

堆和栈区别
堆和栈区别

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

2588

2023.08.10

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

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

6107

2023.07.18

堆和栈区别
堆和栈区别

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

2588

2023.08.10

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

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

4358

2023.08.10

数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

3151

2023.11.13

drop和delete的区别
drop和delete的区别

drop和delete的区别:1、功能与用途;2、操作对象;3、可逆性;4、空间释放;5、执行速度与效率;6、与其他命令的交互;7、影响的持久性;8、语法和执行;9、触发器与约束;10、事务处理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

945

2023.12.29

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

60

2026.10.22

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习

Buffalo框架快速入门指南
Buffalo框架快速入门指南

共0课时 | 0人学习

Valgrind支持平台说明
Valgrind支持平台说明

共0课时 | 0人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn