CS50 PSet4 Recover程序遇Segmentation fault (core dumped)错误求助
解决CS50 PSet4 Recover程序的段错误问题
你的段错误直接原因是未初始化的img指针被调用了fwrite,具体问题和修复方案如下:
问题根源
- 你声明了
FILE *img;但未初始化,它是一个野指针。如果输入文件的第一个512字节块不是JPG起始标志,程序会直接进入else分支执行fwrite,此时img指向随机内存,触发非法内存访问。 - 你没有检查
fopen的返回值——如果因为权限、磁盘空间不足等原因导致JPG文件创建失败,img会变成NULL,后续的fwrite同样会引发段错误。 - 程序结尾的
fclose(img)没有判断img是否有效,若从未打开过任何JPG文件,关闭空指针也会出问题。
修复步骤
- 初始化
img为NULL,避免野指针。 - 在else分支添加
img有效性判断,仅当已经打开了JPG文件时才执行写入。 - 检查
fopen返回值,处理文件创建失败的情况。 - 关闭
img前先判断是否有效,避免操作空指针。
修改后的完整代码
#include <stdio.h> #include <stdlib.h> #include <stdint.h> int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: ./recover IMAGE\n"); return 1; } FILE *file = fopen(argv[1], "r"); if (file == NULL) { printf("File entered does not exist\n"); return 1; } typedef uint8_t BYTE; BYTE buffer[512]; char filename[8]; int i = 0; FILE *img = NULL; // 初始化img为NULL,避免野指针 while (fread(buffer, 1, 512, file) == 512) { if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) { // 若已有打开的img文件,先关闭 if (img != NULL) { fclose(img); } sprintf(filename, "%03i.jpg", i); img = fopen(filename, "w"); // 检查文件是否成功创建 if (img == NULL) { printf("Failed to create %s\n", filename); fclose(file); return 1; } i += 1; fwrite(buffer, 1, 512, img); } else { // 仅当img已打开时才写入数据 if (img != NULL) { fwrite(buffer, 1, 512, img); } } } // 关闭最后一个打开的img文件(如果存在) if (img != NULL) { fclose(img); } fclose(file); return 0; }
额外优化说明
- 合并了原代码中
if(i==0)和else的重复逻辑,让代码更紧凑易读。 - 所有涉及
img的操作都增加了非空判断,从根源上杜绝非法内存访问。
内容的提问来源于stack exchange,提问作者ManveerD
相关产品推荐
相关产品推荐

