如何从nvcc编译的代码中打印带调试符号的堆栈跟踪?
NVCC 编译时 Boost 堆栈跟踪仅输出内存地址的解决方法
核心原因
NVCC 作为编译调度器,会分离处理CUDA设备代码和主机端C++代码:
- 直接传入的
-g参数默认仅作用于设备端代码编译,不会透传给底层的gcc主机编译器,导致主机端代码没有生成完整调试符号 - NVCC 默认给主机编译器传递O2优化等级,会自动开启帧指针省略,导致栈遍历逻辑无法正确回溯调用链
- 代码中定义了
BOOST_STACKTRACE_USE_ADDR2LINE宏,却链接了仅支持地址输出的boost_stacktrace_basic库,没有链接对应addr2line解析的实现库
修复配置
按以下要求调整编译参数即可:
- 用
-Xcompiler前缀向主机编译器透传必要参数:-g:生成主机端DWARF调试符号-fno-omit-frame-pointer:禁用帧指针省略,保证栈回溯正常-rdynamic:导出所有全局符号到动态符号表,提升运行时符号解析成功率
- 链接匹配的Boost栈跟踪库:使用
boost_stacktrace_addr2line替代boost_stacktrace_basic,补充链接依赖的lrt库 - 编译全程不要加
-s参数,不要对生成的二进制执行strip操作,避免调试符号、符号表被删除
验证可用的编译命令
nvcc -g -lineinfo -Xcompiler "-g -fno-omit-frame-pointer -rdynamic" main.cpp -lboost_stacktrace_addr2line -ldl -lrt
额外添加的
-lineinfo为可选参数,用于生成CUDA设备侧代码的行号信息,后续如果需要在核函数中打印栈跟踪可以保留,不影响主机侧栈跟踪效果。
编译后执行二进制即可输出包含函数名、源码绝对路径、对应行号的完整堆栈,和clang编译的输出效果一致。如果要确认调试符号是否正确生成,可以执行readelf -S ./a.out | grep debug,输出中存在多个debug前缀的段即表示符号正常。
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

