使用realloc后所有数组索引指向同一数据的技术问题排查
C语言动态字符数组异常:所有元素显示同一内容的问题排查与解决
问题根源
兄弟,这个问题我太熟了!你代码里的lines[counter] = nextline;这行就是核心bug!
nextline是一个栈上的局部字符数组(char nextline[1024];),每次循环执行fgets时,都会把读取到的玩家数据覆盖到这块固定的栈内存里。而你只是把nextline的内存地址赋值给lines数组的每个元素——这意味着lines里的300个指针,全指向了同一块内存区域!
当循环结束后,nextline里存的是最后一次读取的玩家数据,所以你后续访问所有lines元素时,看到的自然都是这最后一份内容。更糟的是,nextline是栈变量,函数执行完毕后这块内存会被系统回收,后续访问还可能触发崩溃或读取垃圾值的未定义行为。
解决方案
要解决这个问题,你需要为每个读取到的字符串分配独立的堆内存,并把内容复制进去,而不是直接复用栈内存的地址。这里有两种常用方法:
方法1:用strdup快速复制字符串(简便但依赖POSIX标准)
strdup会自动完成内存分配和字符串复制,直接替换赋值那一行即可:
lines[counter] = strdup(nextline);
注意:
strdup不是C语言标准库函数,但绝大多数主流编译器(GCC、Clang、MSVC等)都支持它。
方法2:手动malloc+strcpy(标准C兼容,更稳妥)
如果需要严格遵循C标准,或者要处理内存分配失败的情况,推荐用这种方式:
// 为当前字符串分配内存:长度+1(用于存储字符串终止符'\0') lines[counter] = malloc(strlen(nextline) + 1); // 一定要检查内存分配是否成功,避免空指针访问 if (lines[counter] == NULL) { // 分配失败时,要先释放已分配的内存,避免泄漏 for (int i = 0; i < counter; i++) { free(lines[i]); } free(lines); fclose(fd); printf("内存分配失败!\n"); return; } // 把nextline的内容复制到新分配的内存里 strcpy(lines[counter], nextline);
额外注意事项
使用完lines数组后,别忘了释放内存避免泄漏:
// 先逐个释放每个字符串的内存 for (int i = 0; i < *numElements; i++) { free(lines[i]); } // 最后释放lines数组本身 free(lines);
内容的提问来源于stack exchange,提问作者Rafael Botas
相关产品推荐
相关产品推荐

