32位ARM平台nt98566上strlen返回值if判断异常问题求助
问题:strlen返回值与整数比较出现异常的排查与解决
代码场景
char stack_protect[1000] = {0}; char temp[100] = { 0 }; memset(&temp, 1, 110); int len = strlen(temp); printf("test strlen of temp %d \n", len); if (len > 100) { // 预期执行此处,但实际进入else分支 } else { // 实际执行分支 } char stack_protect2[1000] = {0};
异常现象
strlen(temp)返回值为110,打印输出也确认这一点,但if(len > 100)的判断结果为false。
运行环境:Linux系统、32位ARM架构、SOC为nt98566。
已完成的测试
- 将
len赋值给新的int变量len1后,if(len1 > 100)判断结果为true:char temp[100] = { 0 }; memset(&temp, 1, 110); int len = strlen(temp); int len1 = len; if (len1 > 100) // 结果为TRUE - 查看
len的内存字节:0x6e, 0x00, 0x00, 0x00(对应十进制110,小端存储) - 在hisiv300 SOC上执行相同逻辑,
len=110时if(len>100)判断结果为true。
原因分析
- 栈越界引发未定义行为:
temp是100字节数组,但memset(&temp, 1, 110)越界写入10字节,直接破坏栈上相邻内存区域。栈帧被破坏后,编译器的优化逻辑失去可靠依据,导致len的存储或比较逻辑出现异常。 - 类型转换与编译器优化叠加问题:
strlen返回值类型为size_t(32位ARM下是unsigned int),你将其赋值给signed int类型的len。nt98566对应的编译器(大概率是特定版本GCC)的激进优化下,可能直接用strlen的无符号返回值参与比较,而非读取len的实际存储值;或者栈越界导致编译器无法正确追踪len的取值,触发不符合预期的优化判断。
解决方案
- 修复栈越界(核心):立即修正
memset的写入长度,确保不超过数组大小:
栈越界属于未定义行为,所有后续异常都可能由此引发,必须优先修复。memset(temp, 1, sizeof(temp)); // 写入长度改为数组实际大小100 - 统一变量类型:将
len的类型改为size_t,避免无符号/有符号类型转换陷阱:size_t len = strlen(temp); if (len > 100) { // 逻辑代码 } - 显式类型转换(临时兼容):如果必须用
int存储,比较时显式转换为size_t:int len = (int)strlen(temp); if ((size_t)len > 100) { // 逻辑代码 } - 临时关闭优化排查:添加编译选项
-O0关闭所有优化,验证是否为优化导致的异常,但最终仍需以修复栈越界为根本解决办法。
内容的提问来源于stack exchange,提问作者shunji XIE
相关产品推荐
相关产品推荐

