You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AddressSanitizer拦截__isoc99_sprintf时栈溢出崩溃的解决办法

问题解决方案与分析

核心问题根源

你遇到的崩溃是由于混合编译的ELF文件包含GCC 4.4.7(早于ASAN集成的GCC 4.8版本)编译的代码,导致libasan在拦截__isoc99_sprintf符号时,触发了dlsym/_dlerror_run/free的递归调用循环——ASAN尝试查找原函数时调用了dlsym,而dlsym依赖的free又被ASAN拦截,进而再次触发符号查找,最终栈溢出崩溃。

具体解决方法

1. 修正ASAN_OPTIONS的函数拦截排除配置

之前取消拦截失败大概率是参数格式错误,尝试以下两种正确配置:

  • 直接禁用sprintf系列函数的拦截:
    ASAN_OPTIONS=intercept_sprintf=0 LD_PRELOAD=/usr/lib64/libasan.so.5 ./your_program
    
  • 精确排除__isoc99_sprintf:
    ASAN_OPTIONS=exclude_functions=__isoc99_sprintf LD_PRELOAD=/usr/lib64/libasan.so.5 ./your_program
    
    注:libasan.so.5对应GCC 8.5版本的ASAN库,路径需根据实际系统调整。

2. 重新编译老代码模块(最彻底方案)

将所有用GCC 4.4.7编译的代码模块,改用GCC 8.5重新编译,并添加ASAN编译选项:

gcc -fsanitize=address -O1 -g your_old_module.c -c -o your_old_module.o

然后重新链接整个程序,确保所有模块都与GCC 8.5的libasan兼容——老GCC编译的代码无ASAN instrumentation,与新libasan的符号拦截逻辑天然冲突,重编译可彻底消除这类问题。

3. 调整动态加载顺序避免递归循环

尝试让系统libdl优先于libasan加载,避免ASAN拦截dlsym时触发递归:

LD_PRELOAD=/lib64/libdl.so.2:/usr/lib64/libasan.so.5 ./your_program

可配合LD_DEBUG=symbols查看符号解析过程,确认是否存在符号优先级冲突:

LD_DEBUG=symbols ASAN_OPTIONS=verbosity=2 LD_PRELOAD=/lib64/libdl.so.2:/usr/lib64/libasan.so.5 ./your_program

4. 使用静态链接的ASAN

编译时改用静态链接ASAN,避免动态加载时的符号冲突:

gcc -fsanitize=address -static-libasan your_program.c -o your_program

静态链接会将ASAN逻辑直接嵌入程序,减少动态符号解析的不确定性,但需注意静态链接可能不支持某些系统功能(如动态加载其他库)。

其他可能的排查方向

  • 检查符号版本冲突:用readelf -s your_program | grep __isoc99_sprintf查看该符号的版本信息,确认是否存在新旧GCC版本的符号共存问题,可通过LD_VERSION_MASK环境变量限制符号版本。
  • 排查自定义重载函数:用nm your_program | grep -E 'dlsym|free'检查程序是否重载了dlsym或free,这类自定义函数会与ASAN的拦截逻辑直接冲突,需修改代码移除重载。

内容的提问来源于stack exchange,提问作者joepol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:38:35