调用fopen()时触发Segmentation Fault,求故障原因分析
段错误原因分析与修复方案
这问题我帮你拆解下,你的代码触发段错误大概率是踩了两个C语言里的常见坑,咱们一个个说:
1. 未检查文件是否成功打开
你的代码里直接用fopen(small, "r")的返回值去调用fscanf,但如果small.ppm不存在、路径不对,或者程序没有读取权限,fopen会返回NULL。这时候对NULL指针执行fscanf操作,直接就会触发段错误——这是最常见的原因之一。
2. 缓冲区溢出风险
你定义了char word[5];,这个数组最多只能存4个有效字符(因为C字符串需要末尾的'\0'终止符)。如果small.ppm里的第一个单词长度≥5,fscanf("%s", word)会不管数组大小,一个劲往里面写数据,直接溢出缓冲区,破坏栈上的其他内存数据,进而触发段错误(或者其他不可预测的未定义行为)。
修复后的代码
#include <stdio.h> #include <string.h> int main(void) { const char *small = "small.ppm"; // 字符串字面量建议用const修饰,避免意外修改 FILE *fp; char word[64]; // 用足够大的缓冲区,适配大多数场景 int read_result; // 必须检查文件是否成功打开 fp = fopen(small, "r"); if (fp == NULL) { perror("Failed to open file"); // 打印具体错误原因,方便排查 return 1; } // 限制读取字符数,避免缓冲区溢出:%63s表示最多读63个字符,留1个位置给'\0' read_result = fscanf(fp, "%63s", word); if (read_result != 1) { fprintf(stderr, "Failed to read from file\n"); fclose(fp); // 失败也要记得关文件 return 1; } printf("%s\n", word); fclose(fp); // 用完文件及时关闭,避免资源泄漏 return 0; }
修复点说明
- 检查fopen返回值:用
if (fp == NULL)判断文件是否打开成功,配合perror能直接打印错误原因(比如文件不存在、权限不足),方便排查问题。 - 限制读取长度:
%63s强制fscanf最多读取63个字符,刚好适配word[64]的大小,从根源避免缓冲区溢出。 - const修饰字符串字面量:字符串字面量在内存中是只读的,用
const修饰可以防止意外修改导致的未定义行为。 - 关闭文件:无论程序执行成功还是失败,都要关闭打开的文件,避免文件描述符泄漏。
内容的提问来源于stack exchange,提问作者Christian Lindemann
相关产品推荐
相关产品推荐

