C语言字符串数组元素被覆盖问题:原因及解决方案
C语言数组指针指向同一块内存导致的输出异常分析与解决
问题代码
// open file FILE *file = fopen(filename, "rb"); // create buffer & lines array char buffer[512]; char *lines[512]; // create index int length = 0; while (fgets(buffer, sizeof(buffer), file)) { // update & test lines[length] = buffer; printf("(1) %s", lines[length]); // ++ length++; } // print nl separator printf("\n"); // output for (int i = 0; i < length; i++) printf("%s\n", lines[i]);
控制台输出
(1) line 1 (1) line 2 (1) line 3 line 3 line 3 line 3
问题原因
核心问题是**lines数组里的所有指针都指向同一块栈内存buffer**:
- 每次执行
fgets(buffer, ...)时,都会将读取到的新内容覆盖buffer中的旧数据; - 第一个循环中,打印的是
buffer当前的实时内容,所以能正常显示每一行; - 第二个循环执行时,
buffer已经被最后一次fgets写入的内容(line 3)覆盖,而lines里的所有指针都指向这块内存,因此输出全是最后一行。
解决方案
方案1:使用strdup复制每行内容
strdup会自动分配内存并复制字符串,注意使用后要手动释放内存避免泄漏:
// open file FILE *file = fopen(filename, "rb"); if (!file) { // 增加文件打开失败的判断 perror("fopen failed"); return 1; } char buffer[512]; char *lines[512]; int length = 0; while (fgets(buffer, sizeof(buffer), file) && length < 512) { // 增加数组越界保护 lines[length] = strdup(buffer); if (!lines[length]) { // 检查内存分配失败 perror("strdup failed"); // 释放已分配的内存 for (int j = 0; j < length; j++) free(lines[j]); fclose(file); return 1; } printf("(1) %s", lines[length]); length++; } printf("\n"); // 输出内容 for (int i = 0; i < length; i++) printf("%s\n", lines[i]); // 清理资源 for (int i = 0; i < length; i++) free(lines[i]); fclose(file);
方案2:手动分配内存并复制
如果环境不支持strdup,可以用malloc+strcpy实现:
// 替换循环内的strdup部分 size_t line_len = strlen(buffer); lines[length] = malloc(line_len + 1); // +1用于存储字符串结束符'\0' if (!lines[length]) { perror("malloc failed"); // 清理已分配资源 for (int j = 0; j < length; j++) free(lines[j]); fclose(file); return 1; } strcpy(lines[length], buffer);
内容的提问来源于stack exchange,提问作者user19435240
相关产品推荐
相关产品推荐

