如何用系统调用在C语言中读取文件每行并存储至内存?求助排查问题
问题分析与修正方案
你的代码存在的核心问题
- 指针指向重复且栈内存不安全:
temp是栈上分配的数组,你把files[j] = temp,所有数组元素的指针都会指向同一块栈内存。后续循环修改temp时,之前存入的内容会被覆盖,程序退出当前函数后,栈内存释放,这些指针会变成野指针,访问会导致未定义行为。 - 缺少字符串结束符:C语言字符串必须以
\0结尾,你的代码在存入temp后没有添加这个结束符,后续使用这些字符串(比如打印)会读取到内存中的垃圾数据。 - 未处理无换行的最后一行:如果文件最后一行没有以
\n结尾,循环结束后这部分内容不会被存入数组。 - 缓冲区溢出风险:
temp固定长度100,若某一行超过99个字符(留一个位置给\0),会导致缓冲区溢出,破坏栈上其他数据。 - 未处理文件打开失败:
open可能返回-1(比如文件不存在),直接使用fd会出错。
修正后的代码示例
我们可以用动态分配内存来解决指针指向问题,同时修复其他缺陷:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "用法: %s <文件名>\n", argv[0]); exit(1); } char *files[100]; // 最多存100行 char buffer; int i = 0, j = 0; // 初始分配一块小内存,后续按需扩容 char *temp = malloc(100 * sizeof(char)); if (!temp) { perror("malloc失败"); exit(1); } size_t temp_capacity = 100; int fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("打开文件失败"); free(temp); exit(1); } while (read(fd, &buffer, 1) > 0) { if (buffer != '\n') { // 检查缓冲区是否已满,满了就扩容 if (i >= temp_capacity - 1) { temp_capacity *= 2; char *new_temp = realloc(temp, temp_capacity * sizeof(char)); if (!new_temp) { perror("realloc失败"); free(temp); close(fd); exit(1); } temp = new_temp; } temp[i++] = buffer; } else { // 添加字符串结束符 temp[i] = '\0'; // 为当前行分配独立内存,拷贝temp内容 files[j] = malloc(strlen(temp) + 1); if (!files[j]) { perror("malloc失败"); // 释放已分配的内存 for (int k = 0; k < j; k++) { free(files[k]); } free(temp); close(fd); exit(1); } strcpy(files[j], temp); j++; if (j >= 100) { fprintf(stderr, "超过最大行数限制100\n"); break; } i = 0; } } // 处理最后一行没有换行的情况 if (i > 0) { temp[i] = '\0'; files[j] = malloc(strlen(temp) + 1); if (!files[j]) { perror("malloc失败"); for (int k = 0; k < j; k++) { free(files[k]); } free(temp); close(fd); exit(1); } strcpy(files[j], temp); j++; } // 示例:打印所有读取到的行 printf("读取到%d行内容:\n", j); for (int k = 0; k < j; k++) { printf("%s\n", files[k]); } // 释放所有分配的内存 for (int k = 0; k < j; k++) { free(files[k]); } free(temp); close(fd); return 0; }
关键改进点
- 动态分配独立内存:每行内容都用
malloc分配独立的内存块,避免所有指针指向同一块栈内存的问题。 - 缓冲区自动扩容:通过
realloc动态调整临时缓冲区大小,避免固定长度导致的溢出。 - 添加字符串结束符:确保每个存储的字符串都是合法的C语言字符串。
- 处理边界情况:包括文件打开失败、最后一行无换行、超过最大行数限制等。
- 内存泄漏防护:在出错时释放已分配的内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Rui Barbosa
相关产品推荐
相关产品推荐

