使用fgets时触发Segmentation Fault的问题排查求助
分析与修复C语言文件读取函数的段错误问题
核心错误:realloc参数错误引发内存越界
你的代码中首次调用malloc时正确计算了所需字节数:malloc(sizeof(int) * limit),但后续realloc调用存在致命错误:
values = realloc(values, limit);
realloc的第二个参数要求传入字节数,但你传入的是元素个数limit。当limit增加到201时,realloc仅分配201字节,而实际需要201 * sizeof(int)字节(32位系统下为804字节)。内存分配不足会导致后续写入values[i]时越界,破坏堆内存结构。当循环执行到第106次时,堆结构的损坏已经影响到FILE指针fp或fgets的内部缓冲区,最终触发段错误。
其他潜在问题
- 未检查
fopen返回值:若文件不存在或无权限打开,fp会为NULL,直接调用fgets会触发段错误。 - 未处理
realloc失败场景:realloc内存不足时返回NULL,直接赋值给values会丢失原指针,造成内存泄漏。 fgets缓冲区截断风险:若文件中某行数字长度超过DIGITS_MAXIMUM_NUMBER-1,fgets会截断数据,剩余字符留在输入缓冲区,后续读取会得到错误的分段数据。
修正后的代码
#define DIGITS_MAXIMUM_NUMBER 10 int* read_from_file(const char* file_name) { int limit = 101; int *values = malloc(sizeof(int) * limit); // C标准中无需强制转换malloc返回值 if (!values) { // 检查malloc是否成功 return NULL; } FILE *fp = fopen(file_name, "r"); if (!fp) { // 检查文件是否成功打开 free(values); return NULL; } char string_value[DIGITS_MAXIMUM_NUMBER]; int i = 1; while(fgets(string_value, DIGITS_MAXIMUM_NUMBER, fp) != NULL) { if (i >= limit) { limit += 100; int *temp = realloc(values, sizeof(int) * limit); // 传入正确的字节数 if (!temp) { // 处理realloc失败 free(values); fclose(fp); return NULL; } values = temp; } values[i] = atoi(string_value); i++; if (i >= 106) printf("%d\n", i); } values[0] = i; // 收缩内存至实际所需大小(失败时保留原指针,避免内存丢失) int *temp = realloc(values, sizeof(int) * i); if (temp) { values = temp; } fclose(fp); return values; }
内容的提问来源于stack exchange,提问作者Francesco
相关产品推荐
相关产品推荐

