C语言循环内调用strcat导致循环变量r异常、循环次数错乱问题
问题原因
该异常由栈缓冲区溢出导致:strcat函数执行时的越界写入操作,直接篡改了栈空间上存储的循环变量r,最终造成循环逻辑失控。
问题复现逻辑
- 函数内定义的
temp数组仅分配了15字节空间,初始化后仅预留14字节可用于存储字符串内容,剩余1字节必须存放字符串结束符\0。 strcat本身不做任何边界检查,会把源字符串从起始位置到\0的全部内容,直接追加到目标字符串末尾:- 第一次循环(r=0,i=0):追加
abcdef及结束符,temp共占用7字节,未越界 - 第二次循环(r=1,i=1):追加
bcdef及结束符,temp共占用12字节,未越界 - 第三次循环(r=2,i=2):追加
cdef及结束符,temp共需要16字节存储空间,已经超出15字节的数组边界。多写入的内容会直接覆盖栈上temp相邻位置的内存,而局部变量r恰好分配在这片相邻栈空间上,值首先被结束符\0改写为0 - 后续循环的越界写入会持续覆盖
r的存储空间,最终把r改成无意义的垃圾值(即输出中看到的1717920769),循环判断条件r < 11完全失效。
- 第一次循环(r=0,i=0):追加
- 注释掉
strcat调用后不存在越界写入操作,栈上的r不会被篡改,因此循环可以正常执行。
修复方法
- 为
temp数组分配足够容纳所有拼接内容的存储空间,必须预留1字节存放字符串结束符\0 - 调用
strcat前增加长度校验,避免写入内容超出数组边界
参考修复代码:
#include <stdio.h> #include <string.h> void scan_eqn (char *eqn) { // 扩大数组容量,预留足够拼接空间 char temp[128] = ""; int i, r; for (i = 0, r = 0; r < 11; r++, i++) { // 拼接前做长度校验,从根源避免溢出 if (strlen(temp) + strlen(eqn + i) + 1 > sizeof(temp)) { break; } strcat (temp, eqn + i); printf("r: %d ", r); } printf("\n\n\n"); } int main() { char eq[50]; printf("Enter the sentence: "); scanf("%[^\n]s", eq); scan_eqn(eq); return 0; }
内容的提问来源于stack exchange,提问作者World Producer
相关产品推荐
相关产品推荐

