C语言如何将文件内容按行存入指针数组?读取函数输出异常排查
异常原因排查
- 核心逻辑缺陷:循环内
data[len] = buffer;仅将栈上局部数组buffer的首地址存入指针数组,未做内容拷贝。所有data元素实际指向同一块固定的栈内存地址,每轮fgets都会覆盖这块内存的内容,循环结束时内存中留存的是文件最后一行,自然出现所有条目重复输出最后一行的现象。同时栈内存仅在fileRead函数执行期间有效,函数返回后栈空间会被其他逻辑复用覆盖,会进一步触发乱码、无输出的未定义行为。 - 权限判断错误:两个判断分支完全重复,都使用
access(path, F_OK)做存在性校验,本该用于校验读权限的分支没有做有效判断;且代码未对fopen返回的文件指针做非空校验,一旦文件打开失败,传入空指针调用fgets会直接触发程序异常,对应出现无任何输出的现象。 - 参数不一致:定义
buffer长度为1030字节,但fgets调用时传入的读取长度为1024,属于设计冗余,虽不直接触发崩溃,但会造成不必要的读取截断。
正确实现方案
核心修正点:
- 每读取一行,为当前行动态分配独立的堆内存块,将缓冲区内容拷贝到独立内存中存储,避免所有指针指向同一块临时内存
- 补全权限校验逻辑,区分文件存在性、读权限的校验规则
- 增加文件指针非空校验、数组越界保护,避免空指针、数组越界的未定义行为
- 补充动态内存的释放逻辑,避免内存泄漏
修正后的可运行代码如下:
#include <stdio.h> #include <stdint.h> #include <string.h> #include <unistd.h> #include <stdlib.h> int fileRead(char *path, char *data[], int maxLines){ int len = 0; char buffer[1030]; FILE *fp; // 校验文件存在性 if(access(path, F_OK) != 0){ printf("file not exists.\n"); return -1; } // 校验文件读权限 if(access(path, R_OK) != 0){ printf("No read permission.\n"); return -1; } fp = fopen(path, "r"); // 校验文件打开结果 if(fp == NULL){ printf("open file failed.\n"); return -1; } while(fgets(buffer, sizeof(buffer), fp) != NULL){ // 防止指针数组越界 if(len >= maxLines){ break; } // 为当前行分配独立堆内存 data[len] = malloc(strlen(buffer) + 1); if(data[len] == NULL){ break; } // 拷贝行内容到独立内存空间 strcpy(data[len], buffer); len++; } fclose(fp); return len; } int main(){ char *path = "addr"; char *data[1024] = {}; // 传入指针数组的最大可存储行数,避免越界 int maxLines = sizeof(data) / sizeof(data[0]); int len = fileRead(path, data, maxLines); if(len > 0){ for(int i = 0; i < len; i++){ printf("%s", data[i]); // 释放动态分配的内存,避免泄漏 free(data[i]); data[i] = NULL; } } return 0; }
内容的提问来源于stack exchange,提问作者Gerrie
相关产品推荐
相关产品推荐

