AddressSanitizer (ASan) 使用示例
环境信息
| 项目 | 状态 |
|---|---|
| 系统 | Ubuntu 20.04 x86_64 |
| GCC | 9.4.0 |
| libasan | libasan.so.5 ✅ |
| 项目 | front6.3 / sipgate.exe |
一、启用 ASan
编辑 /home/w/c/6.3/front6.3/CMakeLists.txt,找到第 29-30 行,解注释以下两行:
add_compile_options(-fsanitize=address -fno-omit-frame-pointer -fno-common)
add_link_options(-fsanitize=address)
⚠️ 使用完毕后记得重新注释这两行,ASan 会使程序性能下降约 2-3 倍,不适用于生产环境。
二、重新编译
cd /home/w/c/6.3/front6.3/build
cmake .. # 必须重新 cmake,使新编译选项生效
make -j11
三、运行并收集报告
方式 1:输出到文件(推荐)
报告写入 /home/logs/asan/asan_report.<pid>,程序崩溃后不丢失。
mkdir -p /home/logs/asan
ASAN_OPTIONS="log_path=/home/logs/asan/asan_report:halt_on_error=0:detect_stack_use_after_return=1:detect_leaks=0" \
./sipgate.exe -m cfgfile
方式 2:stderr 重定向
./sipgate.exe -m cfgfile 2>/home/logs/asan/asan_report.log
方式 3:同时输出到控制台和文件
./sipgate.exe -m cfgfile 2>&1 | tee /home/logs/asan/asan_report.log
四、常用 ASAN_OPTIONS 选项
| 选项 | 说明 |
|---|---|
log_path=<路径前缀> | 报告写入 <路径前缀>.<pid> 文件 |
halt_on_error=0 | 检测到错误后继续运行,可收集更多问题(默认=1立即中止) |
halt_on_error=1 | 检测到第一个错误立即终止,适合定位单一问题 |
detect_stack_use_after_return=1 | 检测栈变量 use-after-return(默认关闭) |
detect_leaks=0 | 关闭内存泄漏检测,聚焦堆损坏问题 |
detect_leaks=1 | 开启内存泄漏检测 |
print_stats=1 | 程序退出时打印内存使用统计 |
verbosity=1 | 输出更详细的 ASan 运行信息 |
abort_on_error=1 | 错误时产生 core dump(结合 gdb 分析) |
多个选项用 : 分隔:
ASAN_OPTIONS="log_path=/home/logs/asan/report:halt_on_error=0:detect_leaks=0:detect_stack_use_after_return=1"
五、报告解读
ASan 报告结构如下,可以精确定位首次非法内存操作的位置:
==<pid>==ERROR: AddressSanitizer: heap-use-after-free on address 0x...
<错误类型>: READ/WRITE of size N at 0x... thread T3
// 出错时的调用栈(定位使用者)
#0 0x... in xxx::xxx() File.cpp:50
#1 0x... in yyy::yyy() File.cpp:30
// 该内存被释放时的调用栈(定位释放者)
freed by thread T1 here:
#0 0x... in operator delete
#1 0x... in moduleend JtGbModuleFactory.cpp:67
// 该内存最初被分配时的调用栈
allocated by thread T0 here:
#0 0x... in operator new
#1 0x... in GbsPlatform::CreateGetPlatformChnStreamCfgTask GbsPlatform.cpp:86
常见错误类型:
| 错误类型 | 含义 |
|---|---|
heap-use-after-free | 使用已释放的堆内存(最常见) |
heap-buffer-overflow | 堆缓冲区越界写 |
stack-use-after-return | 使用已返回函数的栈变量 |
double-free | 对同一内存 delete 两次 |
use-after-poison | 使用已被标记为不可访问的内存 |
六、当前项目疑似崩溃位置(供参考)
- 崩溃信号:
SIGABRT由malloc_printerr→_int_free触发(堆元数据损坏) - 崩溃栈:
switch_callback→delete this→~lambda(urll)→_int_free - 疑似根因:
moduleend中delete subctx过早执行,或并发 HTTP 请求下ctx生命周期管理问题 - 相关文件:
gbs/JtGbModuleFactory.cpp—CreateJtHttpTasklambda 及moduleendgbs/platform/GbsPlatform.cpp—CreateGetPlatformChnStreamCfgTaskworkflow-0.11.7/src/factory/WFTaskFactory.inl—switch_callback/done
ASan 预期会在以下位置报告 heap-use-after-free:
gbs/JtGbModuleFactory.cpp:67 (delete subctx) ← 释放点
gbs/platform/GbsPlatform.cpp:104 ← 或后续访问点
112

被折叠的 条评论
为什么被折叠?



