某 arm 工控机在试点测试时发现,一旦有数据到,工控机界面会就卡住,测试人员此问题必现,经查日志为段错误,多次在相同代码位置出错。除去周末,经过一天多时间,解决了问题,虽然没有很难的技术问题,但过程还是值得记录的。
由于本文没有技术含量,请谨慎按需阅读。
上周五早上,测试人员(很不幸,我还无资格称之为同事)正在去试点路上,打电话给我,说要更新软件版本,于是我拉取代码树上最新的release分支。基于手上没有 arm 的编译环境,于是打包发给他,让他在测试机上编译并测试。后来才知道,那是目前唯一一台集编译和测试于一体的一体机。编译好后,指导如何更新,近中午时反馈出现段错误,因为有其它事,到下午时才找日志看。由于那个工程我没有参与,所以找相应开发人员看,经查,问题定位到一个初始化语句std::string foobar = "";
,四只眼睛分析半天没结论。经商量,把试点的机器搬回来,在实验室重现,再跟踪调试。
咨询测试人员,反馈说在实验室相同场景测试时没有遇到问题。由于实验室均为x86机器,也没错误,只能加打印调试。
先是在出错那一行代码前面加上一些语句,测试,发现出错的行号变化了,依然指向那个string
语句。再仔细观察代码,发现这个string
类型变量在函数后面赋值给另一个数组(char buff[]
),于是怀疑数组容量不够,将组装后的string
变量长度打印,发现超过了数组长度。将长度加大,测试,一切正常。使用工程封装的log函数打印,发现URL地址的中文输出有乱码,但用printf
输出正常。URL的转义是通过调用curl
库函数curl_easy_escape
实现的,中文字符会带了百分号%
,怀疑是封装log函数问题,限于时间,没有再研究。不过可能是个隐患,日后再议。
将最后组装的buffer数组容量改大即可。
下面模拟实际工程的函数布局,舍去无关的代码,以突显问题。
注:最后的output会越界。
#include
#include
#include
int main()
{
const char* url = "http://172.168.168.188:18080/api/new/v2/queryAVeryloongApiforveryloongremoteipserver?";
char foo1[256]={0};
int a = 100;
int b = 1;
int c = a+b+1+1+b+3+a;
std::string strData = "";
for (int i=0; i < 3; i++)
{
strData.append("&");
strData.append("10000");
strData.append("=");
strData.append("103");
}
char output[96]={0};
sprintf(output, "%s?%s", url, strData.c_str());
printf("url=%s\n", output);
return 0;
}
经测试,只有x86上正常,其它2个平台段错误。从业多年的直觉认为,x86上应该是看上去正常,实际不正常(肯定是越界了),但一直如此使用,百思不得其解。
在x86工控机上的测试结果:
$ file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=3e7c0c704230b08e49f529a6924397e0dfd358ba, not stripped
$ ./a.out
url=http://172.168.168.188:18080/api/new/v2/queryAVeryloongApiforveryloongremoteipserver??&10000=103&10000=103&10000=103
在arm工控机上的测试结果:
$ file a.out
a.out: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.7.0, not stripped
$ ./a.out
url=http://172.168.168.188:18080/api/new/v2/queryAVeryloongApiforveryloongremoteipserver??&10000=103&10000=103&10000=103
段错误(吐核)
在loongarch工控机上的测试结果:
$ file a.out
a.out: ELF 64-bit LSB executable, LoongArch-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld.so.1, for GNU/Linux 4.15.0, BuildID[sha1]=7d61ce6d3a50850e045dcdaab48585f88bbca4f7, not stripped
$ ./a.out
url=http://172.168.168.188:18080/api/new/v2/queryAVeryloongApiforveryloongremoteipserver??&10000=103&10000=103&10000=103
总线错误
最近断续地接触国产化适配,有点小心得。
与很多人认为的只要改个宏定义,交叉编译一下就行不同,我对适配的事不敢太乐观。上面往往认为三两天就能做完,但实操起来就很麻烦。相同的代码,在不同的架构(x86和arm、mips)上表现不一定相同。
目前较大的问题有下面几个: