0

0

如何使用LeakSanitizer (LSan) 在运行时检测c++内存泄漏? (独立工具)

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-01-10 10:52:02

|

249人浏览过

|

来源于php中文网

原创

LeakSanitizer必须与AddressSanitizer联用,因LSan是libasan内部组件而非独立库;单独使用-fsanitize=leak无效,需配合-fsanitize=address及ASAN_OPTIONS=detect_leaks=1。

如何使用leaksanitizer (lsan) 在运行时检测c++内存泄漏? (独立工具)

LeakSanitizer 不是独立工具,它必须与 AddressSanitizer(ASan)一起编译并运行;单独启用 -fsanitize=leak 无效,链接时会报错或静默忽略泄漏检测。

为什么 -fsanitize=leak 单独不工作

LSan 是 LLVM/Clang 中 ASan 运行时库的一部分,不是可单独加载的 sanitizer。即使你写 -fsanitize=leak,Clang 实际仍会链接 libasan,且仅当 ASAN_OPTIONS=detect_leaks=1(默认开启)时才激活泄漏扫描。GCC 的 LSan 支持更弱,仅在较新版本(≥9)中作为 ASan 的子功能存在,且依赖 libasan

  • -fsanitize=leak 在 Clang 中只是个“占位符”,不触发独立链接行为
  • GCC 8 及更早版本完全不支持 LSan;GCC 9+ 需同时启用 -fsanitize=address
  • 没有 liblsan.so 独立库 —— 所有逻辑都在 libasan 内部,通过环境变量开关

正确启用 LSan 的编译与运行命令

以 Clang 为例,必须启用 ASan 并确保泄漏检测未被禁用:

clang++ -g -O1 -fsanitize=address -fno-omit-frame-pointer main.cpp
ASAN_OPTIONS=detect_leaks=1 ./a.out

关键点:

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

  • -fno-omit-frame-pointer 强烈建议加上,否则堆追踪可能为空或错乱
  • -O1 是推荐优化级:更高(如 -O2)可能导致内联掩盖泄漏源头
  • detect_leaks=1 是默认值,但显式写出更可靠(尤其 CI 环境中 ASAN_OPTIONS 可能被覆盖)
  • 若程序调用 exit() 或 _Exit(),LSan 可能来不及报告 —— 应让 main() 正常返回

常见误报、漏报与绕过场景

LSan 不是万能的,它只扫描进程退出时仍可达的堆内存块,且依赖符号与调试信息:

MetaVoice
MetaVoice

AI实时变声工具

下载
  • 全局指针指向 new 出的内存 → 被视为“仍存活”,**不算泄漏**(这是设计行为,非 bug)
  • 使用 mmap(MAP_ANONYMOUS)malloc 后被 dlclose 卸载的共享库中分配的内存 → **可能漏报**(LSan 不扫描 dlopen 区域)
  • 未带 -g 编译 → 泄漏报告只有地址,无文件/行号,难以定位
  • 程序被 kill -9 终止 → LSan 完全无机会运行,**零报告**
  • C++ static 对象析构函数中发生的 new → 若析构顺序导致指针丢失,可能被误判为泄漏

如何确认 LSan 实际生效

最直接方式:制造一个明确泄漏,看是否报出 indirect leakdirect leak

#include 
int main() {
    new int[100];  // 故意泄漏
    return 0;      // 让 LSan 有机会扫描
}

运行后应看到类似输出:

=================================================================
==12345==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 400 byte(s) in 1 object(s) allocated from:
    #0 0x... in operator new[](unsigned long) .../libasan.so.5
    #1 0x... in main (.../test.cpp:3)

若没输出,检查:

  • 是否用了 ASAN_OPTIONS=detect_leaks=0(包括 shell 环境中残留设置)
  • 是否链接了 -fsanitize=address,而非仅 =leak
  • 是否在 main 返回前调用了 _exit()std::quick_exit()

LSan 的“泄漏”定义严格依赖程序终止时的可达性分析,不是所有未 delete 的内存都会报 —— 它只报那些既没被栈/寄存器/全局变量引用,又没被其他活对象间接持有的内存。这点容易误解,但恰恰是它低误报率的基础。

相关专题

更多
全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

73

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

96

2025.09.18

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

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

384

2023.07.18

堆和栈区别
堆和栈区别

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

568

2023.08.10

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

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

384

2023.07.18

堆和栈区别
堆和栈区别

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

568

2023.08.10

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

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

269

2023.11.13

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

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

208

2023.12.29

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

25

2026.01.09

热门下载

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

精品课程

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

共58课时 | 3.5万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

ASP 教程
ASP 教程

共34课时 | 3.4万人学习

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

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