C语言如何从文本文件读取内容到结构体数组?出现段错误怎么解决
段错误核心原因及修改点
- 野指针访问:原代码中
char * pch;仅声明未分配内存,就直接执行strcpy(pch, line_buf)写入内容,属于非法内存访问,这是触发段错误的最直接原因。实际上不需要额外复制行内容,可直接将line_buf传入strtok使用,若要避免修改原line_buf需先给pch分配与行长度匹配的内存。 - 结构体内存分配错误:给单个
person结构体分配内存时,sizeof (people[line_count-1])取的是指针类型的大小(通常为4/8字节),远小于struct person实际占用的内存,后续访问结构体成员会越界,需改为sizeof(struct person)。 - 空指针未校验:
strtok返回NULL时直接执行strcpy会触发崩溃,需在每次复制前先判断pch是否非空。 - 资源未释放:原代码未关闭打开的文件指针,也未释放临时申请的内存,存在内存泄漏。
修正后可运行代码
#include <stdio.h> #include <stdlib.h> #include <string.h> struct person { char *name; char *phone; char *email; }; int main(void) { int i; int peopleSize = 0; char *pch; FILE *f = fopen("input.txt", "r"); if (f == NULL) return EXIT_FAILURE; // 最多存储100条人员信息 struct person** people = malloc(100 * sizeof(people[0])); if (people == NULL) { fclose(f); return EXIT_FAILURE; } char *line_buf = NULL; size_t line_buf_size = 0; int line_count = 0; ssize_t line_size; // 逐行读取文件 while ((line_size = getline(&line_buf, &line_buf_size, f)) >= 1) { // 去除行尾换行符 if (line_buf[line_size-1] == '\n') { line_buf[line_size-1] = '\0'; line_size--; } if (line_size == 0) continue; // 跳过空行 // 分配结构体内存 people[line_count] = malloc(sizeof(struct person)); if (people[line_count] == NULL) break; // 拆分字段 pch = strtok(line_buf, " "); if (pch == NULL) { free(people[line_count]); continue; } people[line_count]->name = malloc(strlen(pch)+1); strcpy(people[line_count]->name, pch); pch = strtok(NULL, " "); if (pch == NULL) { free(people[line_count]->name); free(people[line_count]); continue; } people[line_count]->phone = malloc(strlen(pch)+1); strcpy(people[line_count]->phone, pch); pch = strtok(NULL, " "); if (pch == NULL) { free(people[line_count]->phone); free(people[line_count]->name); free(people[line_count]); continue; } people[line_count]->email = malloc(strlen(pch)+1); strcpy(people[line_count]->email, pch); line_count++; if (line_count >= 100) break; // 不超过预先分配的100条上限 } peopleSize = line_count; // 打印所有人员信息 for (i = 0; i < peopleSize; i++) { printf("%s\t%s\t%s\n", people[i]->name, people[i]->phone, people[i]->email); } // 释放内存 for (i = 0; i < peopleSize; i++) { free(people[i]->email); free(people[i]->phone); free(people[i]->name); free(people[i]); } free(people); free(line_buf); // 释放getline分配的内存 fclose(f); // 关闭文件 return EXIT_SUCCESS; }
编译运行说明
使用原编译命令即可正常运行:gcc -Wall -O2 -o program filename.c
运行后会输出解析后的人员信息,无段错误,所有申请的内存都会正常释放。
内容的提问来源于stack exchange,提问作者Tobias Meyrick
相关产品推荐
相关产品推荐

