C++程序结合ASAN与UBSAN编译运行触发DEADLYSIGNAL问题求助
ASAN与UBSAN同时链接触发DEADLYSIGNAL问题的解决方案
问题背景
在Ubuntu 22.04.4系统(搭配GCC 11.4.0)中,同时启用AddressSanitizer(ASAN)与UndefinedBehaviorSanitizer(UBSAN)编译程序时,运行会触发AddressSanitizer:DEADLYSIGNAL及段错误。具体表现如下:
测试代码(p.cpp)
int main() { return 0; }
编译命令
c++ -o p p.cpp -fsanitize=address -fsanitize=undefined
运行结果
$ ./p AddressSanitizer:DEADLYSIGNAL AddressSanitizer:DEADLYSIGNAL AddressSanitizer:DEADLYSIGNAL AddressSanitizer:DEADLYSIGNAL AddressSanitizer:DEADLYSIGNAL AddressSanitizer:DEADLYSIGNAL Segmentation fault (core dumped)
验证要点
- 单独使用
-fsanitize=address或-fsanitize=undefined编译,程序可正常运行; - 故障机器编译的可执行文件在ASAN工作正常的机器上能正常执行,排除程序本身问题;
- 全新安装Ubuntu 22.04并安装g++后可稳定复现,部分机器需多次尝试触发,所有Ubuntu 22.04机器均存在该问题;
- gdb调试时,LeakSanitizer提示无法在ptrace环境下工作,无法获取调用栈。
解决方法
该问题是Ubuntu 22.04中GCC 11版本与ASAN+UBSAN组合的已知兼容性问题,可通过以下方式解决:
升级GCC版本
安装GCC 12或更高版本,官方已修复该兼容性问题:sudo apt update && sudo apt install gcc-12 g++-12 # 使用GCC 12编译程序 g++-12 -o p p.cpp -fsanitize=address -fsanitize=undefined禁用LeakSanitizer
若无法升级GCC,可通过环境变量禁用ASAN默认集成的LeakSanitizer,规避冲突:ASAN_OPTIONS=detect_leaks=0 ./p调整UBSAN配置
部分场景下,关闭UBSAN的栈跟踪输出可缓解问题:UBSAN_OPTIONS=print_stacktrace=0 ./p
原因分析
问题根源在于GCC 11中ASAN与UBSAN的初始化逻辑存在冲突,尤其是LeakSanitizer组件在Ubuntu 22.04环境下,与UBSAN的信号处理机制产生竞争,导致触发致命信号。升级GCC版本修复了初始化顺序问题;禁用LeakSanitizer则直接消除了冲突点。
内容的提问来源于stack exchange,提问作者Leandro
相关产品推荐
相关产品推荐

