Address Sanitizer是否仅在进程停止时上报内存泄漏生成ASAN日志?
AddressSanitizer 内存泄漏上报机制结论
首先明确核心结论:
- 你的观察完全符合ASAN的默认工作逻辑:默认配置下ASAN的内存泄漏检测确实仅在进程退出阶段触发上报,运行中不会自动生成泄漏日志,通过终止进程采集ASAN泄漏日志的操作是可行的,只需注意终止方式即可。
具体机制说明
ASAN的内存泄漏检测能力由其集成的LeakSanitizer(LSan)模块实现,默认行为如下:
- LSan启动时会注册
atexit退出钩子,只有当进程走到正常退出流程时,才会遍历进程所有已分配的堆内存块、从全局变量、栈寄存器等根节点出发标记所有可达的内存对象,最终把不可达的泄漏块大小、分配栈等信息整理输出为ASAN日志。 - 进程持续运行阶段,LSan不会自动触发全量堆扫描,因此不会主动输出泄漏相关日志,这就是你观察到运行中无日志、退出后才出日志的原因。
终止进程采集日志的注意事项
不是所有终止进程的操作都能成功触发泄漏上报:
- 可以触发上报的场景:进程自然执行完成正常退出、通过Ctrl+C发送
SIGINT、默认kill命令发送SIGTERM——这类场景下进程有机会执行注册的atexit钩子,能正常走完泄漏扫描和日志输出流程。 - 无法触发上报的场景:用
kill -9发送SIGKILL强杀进程——该信号会被内核直接处理,进程被强制销毁没有机会执行用户态注册的退出钩子,不会输出任何泄漏日志。
运行中不退出进程采集泄漏日志的方法
如果不想终止进程就拿到泄漏报告,可以通过两种方式主动触发检测:
- 代码埋点调用接口:引入头文件
<sanitizer/lsan_interface.h>,在需要检测的位置调用__lsan_do_recoverable_leak_check(),调用时会立刻执行泄漏扫描、输出日志,扫描完成后进程会继续正常运行;如果调用__lsan_do_leak_check(),扫描完成后进程会直接退出。 - 信号触发:启动程序前设置环境变量
LSAN_OPTIONS=handle_sigusr1=1,在进程运行过程中给对应PID发送SIGUSR1信号,进程就会立刻执行一次泄漏扫描并输出日志,不会终止运行。
内容的提问来源于stack exchange,提问作者does_it_really_matters_0104
相关产品推荐
相关产品推荐

