C语言循环中整数意外变更(内存溢出)问题求助
嘿,这个问题我之前也踩过坑!本质是数组越界访问把栈内存搞乱了,咱们一步步说清楚:
首先看你定义的char result[] = "";——这行代码坑很大!当你用空字符串初始化字符数组时,编译器只会给它分配1个字节的空间,刚好够存字符串的终止符\0,完全没有多余空间装你要拼接的"Example String"。
然后你调用strcat(result, string);的时候,strcat不管目标数组有没有空间,它会从result里的\0位置开始,把string的内容挨个字节往内存里写。但result已经没空间了,所以这些多余的字节就会写到栈上的其他内存区域里——而你的循环变量i正好存在这附近!于是第一次拼接后,i的内存被覆盖成了随机值,下一次循环时i不是1而是个乱数,直接导致循环条件崩溃,程序终止。
解决方法
给你三种靠谱的解决思路,按需选:
1. 提前分配足够大的固定数组
如果你能算出最终字符串的最大长度,直接定义一个够大的数组就行。比如你要循环10次,每次拼的"Example String"长度是14,加上终止符总长度是14*10 +1 = 141,那直接这么写:
char result[141] = ""; // 提前留足10次拼接的空间
这样strcat有地方写,就不会乱踩其他变量的内存了。
2. 动态分配内存(灵活适配任意长度)
要是没法预估最终长度,用动态内存分配就很合适,每次拼接前重新计算需要的空间:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char string[] = "Example String"; // 先分配1字节存终止符 char *result = malloc(1); if (result == NULL) { perror("malloc failed"); return 1; } result[0] = '\0'; // 初始化为空字符串 for (int i = 0; i < 10; i++) { printf("%d\n", i); // 计算新的总长度:当前result长度 + string长度 +1(终止符) size_t new_len = strlen(result) + strlen(string) + 1; // 重新分配内存,用temp接收避免分配失败丢失原指针 char *temp = realloc(result, new_len); if (temp == NULL) { perror("realloc failed"); free(result); return 1; } result = temp; strcat(result, string); printf("%s\n", result); } free(result); // 用完记得释放内存,别漏了! return 0; }
这种方法会根据实际拼接的长度调整内存大小,既不浪费空间,也不会越界。
3. 栈上变长数组(C99及以上可用)
如果你的编译器支持C99(现在大部分都支持),也可以用变长数组,先算好总长度再分配:
#include <stdio.h> #include <string.h> int main() { char string[] = "Example String"; const int loop_count = 10; size_t total_len = strlen(string) * loop_count + 1; char result[total_len]; // 根据计算的长度分配栈数组 result[0] = '\0'; // 初始化为空 for (int i = 0; i < loop_count; i++) { printf("%d\n", i); strcat(result, string); printf("%s\n", result); } return 0; }
不过要注意,变长数组是在栈上分配的,如果总长度太大可能会栈溢出,适合长度不大的场景。
最后提醒一句:用strcat这类字符串操作函数时,一定要确保目标缓冲区有足够的空间!内存越界的问题经常会搞出各种诡异的bug(比如变量值突然变乱、程序莫名崩溃),排查起来特别头疼,所以内存边界检查一定要重视。
内容的提问来源于stack exchange,提问作者user8620802

