地震软件SAC运行时卡住的问题定位
发表于 2025/05/27
0
问题描述
Seismic Analysis Code,简写为SAC,是天然地震学领域使用最广泛的数据分析软件包之一。SAC 102.0版本在Kunpeng 920 + openEuler 22.03 LTS SP2上编译通过,但启动后光标一直在闪烁,程序卡住,终端无法操作。问题分析
由于编译时没有显示error信息,因此尝试从源码定位。通过gdb调试,查看调用栈,先进入sac_command_line_options ()函数中:
通过搜索该函数,发现只有sac.c文件中存在这个函数。进入sac_command_line_options ()函数内部,可以看到有一个while循环,因此程序卡住很可能与循环有关。
观察到while中使用到了getopt_long函数,该函数常见于处理命令行选项:将匹配到的选项的值返回,如果没有匹配到则会返回-1,并继续循环匹配命令行选项。在这里cCbBpPdDjJLtgnsh是预先设置的合法的选项列表。
为了判断程序卡住是否与while循环相关,在while中设置打印语句"print("after:while:%c\n", ch);"并且为了方便观察,防止打印过快,设置了每次打印后休眠一秒。
设置打印语句后,重新编译执行,输入sac -C后得到以下结果:
可以看到程序是进入while后卡住的,并且不断输出以下信息"after:while:y",正是前面设置的打印语句所打印的信息。
并且当命令为sac -C时,按理只有一个合法选项'C',因此之后输出的char型变量值都是异常状态、不合法的字符。
于是修改打印语句,将ch变量以数字输出:
执行sac命令(不附带任何选项),运行结果如下:
观察到当命令行没有合法参数时,getopt_long函数会返回int类型的值-1,因此赋值给char变量ch后理应也是-1,可实际是255。
由于该软件之前基于x86开发,char变量默认在x86是signed类型,数值范围在-128~127;而在ARM上则默认是unsigned类型,数值范围在0~255,因此软件运行在ARM上后,出现了char类型符号性的问题:将-1赋给ARM架构里的char变量,-1的补码在unsigned char类型解释下的值就是255,因此变量会存入255。
造成循环的原因是255 != -1,while条件满足,因此一直循环,软件表现为卡住。
解决方法
在编译该件时,添加编译选项:-fsigned-char ,该选项的作用是在ARM中设置char默认为signed char类型。
export CFLAGS="-fsigned-char"
../configure --prefix=/usr/local/sac --enable-editline --build=arm-linux
make
make install
编译后,程序不再无限循环,正常运行: