开发者
资源
【运行报错】在鲲鹏环境下运行BTRIM卡死的解决方案
【运行报错】在鲲鹏环境下运行BTRIM卡死的解决方案
发表于2024/03/20
3080

操作系统:Kylin V10

服务器架构:linux-aarch64

软件栈:系统自带gcc7.3.0、cmake、python3

软件信息:一款生科领域的图形修剪工具,https://github.com/Malfoy/BTRIM

软件测试用例:https://github.com/Malfoy/BCOOL/blob/master/test/lambda_virus.200bp.50x.1percentError.fa.gz

背景现象:

按照BTRIM官方的安装方法,解压源码后,执行命令make安装完成生成btrim二进制,这看起来一切都很顺利,然后再进行测试时出现了卡死,如下图:

cke_19038.png

正常的回显是:

cke_25812.png

根因分析:

从对比日志来看,在鲲鹏环境下执行了命令后一直不输出打印,而正常来看是打印Step 1……等等,通过打印查询代码,发现Step 1出现在代码btrim.cpp的788行,

进入到代码btrim.cpp的788行,在第788行上面代码处进行插桩打印c的值分析,鲲鹏环境进入了while死循环,导致了运行程序时卡死不回显,

代码btrim.cpp的751行定义了char c,752行while循环用了getopt函数赋值给c,与-1进行比较,当c不等于-1时进入了下面循环。

cke_222023.png

这里先说明下:

char类型:char类型是用来存储字符的,它的取值范围是-128~127,占用一个字节的内存空间。char类型可以被看作是signed char类型的一种特殊情况。

unsigned char类型:unsigned char类型也是用来存储字符的,它的取值范围是0~255,占用一个字节的内存空间。unsigned char类型只能存储正数,因为它没有符号位。

继续往下分析,

在while循环里面插桩打印printf("c=%d/n",c)发现,当在鲲鹏环境中,如果执行命令./btrim -u 第1次打印出来的c值时等于117,(可自行查看ASCIIC码表,u对应时117),然后第2次、第3次、第n次打印出来却是255,陷入了死循环

cke_223367.png

cke_261410.png

这是为什么呢?主要还是回归到while循环里面的判断,先是调用了getopt的函数,然后把值赋给了c,最后与-1作比较,

同学们可能误解,117和255不都不是等于-1吗?这看起来没毛病。但是255这个值其实是错误的,但为什么会产生255这个值。这跟前面提到的char和unsinged char联系起来了,

正常来说,getopt函数是只能调用一次的,若第二次调用它的值就是等于-1(这也跟源码作者为什么要跟-1比较,而不是跟0,-2,255等等其他值比较的原因),

回归到代码中也就是说,第一次调用getopt的时候,正常情况下c值是等于117,第二次是等于-1。而在鲲鹏环境中,char默认是unsigned char,它的取值是从0~255,那这明显就是-1不在0~255范围内,导致了返回的c值是错的,这里实际返回的是“255”,不管是“255”还是其他值,反正不是-1,从而进入了死循环。

讲到这里基本上已经知道了根因了,总结下,由于鲲鹏架构的特殊性,char默认是unsigned char,从而导致了程序运行卡死,而在x86架构上char是-128~127,是符合getopt函数的返回。

解决方法:

1、在makefile中CFLAGS后面加上参数-fsigned-char进行编译

2、在btrim.cpp代码中char c改成signed char c进行编译

收藏举报
Level 1
0
帖子
0
粉丝
0
获赞