GCC编译器GFDL-VortexTracker段错误问题定位
发表于 2025/05/30
0
作者 | 曹家智
问题背景
开源软件GFDL-VortexTracker(https://github.com/NOAA-GFDL/GFDL-VortexTracker)用oneAPI C++编译器编译后正常运行。但用GCC编译后运行报Segmentation fault错误,程序异常终止。问题分析
GCC编译器原因排查:
1、设置coredump生成路径
vim /etc/sysctl.conf
kernel.core_pattern = /tmp/core-%e-%p-%t
2、设置debug模式编译运行代码/home/cjz/GFDL-VortexTracker/code/CMakeLists.txt
3、运行测试脚本,生成coredump文件
4、用gdb分析coredump文件
查看堆栈信息
5、查看代码
通过gdb调试定位到代码层,发现是变量sstflag定义问题,由于在用户脚本中将sstflag定义为n,导致程序进入if语句异常终止,如果将if语句注释或者将sstflag定义改为y,程序则正常进行,并输出结果。
官方脚本(左)与用户自定义脚本(右):
同一机器用不同的编译器编译运行测试的结果不一样,要分析其原因得看错误处汇编指令。在运行脚本/pg-weather/model-utils/generate_vortex_track/3b_run_tracker_v202503.sh添加gdb运行二进制gettrk.x二进制文件
然后打断点
break src/tracker/gettrk_subroutines.f:886
运行至汇编指令地址
0x55555565267b <access_subroutines_MOD_tracker+37383>: mov 0xeeade(%rip),%r10 # 0x555555741160 <tracked_parms_MOD_sst>
next进入下一行后,出现段错误
查看当前汇编指令地址
x/i $pc
0x5555556526cd <__access_subroutines_MOD_tracker+37465>: movss %xmm0,(%r10,%rax,4)
oneAPI编译器相应汇编指令地址
查看当前命令的汇编指令
0x41dac8 <access_subroutines_mp_tracker_+59736>: mov $0x6ddee0,%rax
在执行下一步next查看当前命令的汇编指令
0x41dc72 <access_subroutines_mp_tracker_+60162>: mov $0x6dde80,%rax
不同编译器的汇编对比
收集二进制gettrk.x的反汇编文件oneAPI和gcc
objdump -d gettrk.x
GCC
oneAPI
从汇编可以看出,
- GCC 编译的代码使用了相对偏移量和 RIP 寄存器,这可能在某些情况下导致不正确的内存访问,从而引发段错误。
- oneAPI 编译的代码使用了固定的内存地址,避免了 RIP 可能的计算错误,因此能够正常执行.
解决方式:将源码赋值那段加个标志位判断,让代码更加健全,无论用GCC和oneAPI编译器都能编译运行通过。社区上也有相关Issue。