CS50 Recover作业:if条件未执行引发Segmentation Fault求助
CS50 Recover作业:段错误与JPEG判断失效修复
导致段错误的直接原因
你的代码在进入else分支时,直接调用fwrite写入img指针,但程序启动后img初始值为NULL——只有当第一个读取的块是JPEG起始块时,img才会被赋值为有效的文件指针。如果第一个块不是JPEG开头,程序就会对空指针执行写操作,直接触发Segmentation Fault。
修复:
在else分支里加个判断,只有img不为空时才执行写入:
else { printf("else executed\n"); if (img != NULL) { fwrite(buffer, BLOCK_SIZE, 1, img); } }
JPEG判断条件从未触发的原因
你用fopen(argv[1], "r")打开card.raw,这是文本模式,在Windows等系统下会自动转换换行符,破坏二进制数据的完整性,导致JPEG的起始标记(0xff 0xd8 0xff 0xeX)无法被正确识别。即使在Linux系统下,文本模式也可能带来潜在问题,处理二进制文件必须用二进制模式。
修复:
打开文件时改用二进制模式:
FILE *card = fopen(argv[1], "rb");
同时,创建JPEG文件时也用二进制模式写入:
img = fopen(filename, "wb");
其他优化与防错点
- 合并重复代码:你在
this_first_jpeg的两个分支里写了几乎一样的文件创建和写入逻辑,可以合并简化:
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] >= 0xe0 && buffer[3] <= 0xef)) { printf("if executed\n"); if (!this_first_jpeg) { fclose(img); } sprintf(filename, "%03i.jpg", number_file++); img = fopen(filename, "wb"); fwrite(buffer, BLOCK_SIZE, 1, img); this_first_jpeg = false; }
- 检查文件创建是否成功:当前代码没有判断
fopen创建JPEG文件是否成功,建议增加判断避免后续出错:
img = fopen(filename, "wb"); if (img == NULL) { printf("Could not create image file.\n"); fclose(card); return 1; }
- 避免空指针关闭:循环结束后,如果没有找到任何JPEG,
img还是NULL,直接fclose(img)会出错,加个判断:
if (img != NULL) { fclose(img); }
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <stdbool.h> #define BLOCK_SIZE 512 typedef uint8_t BYTE; int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: ./recover FILE\n"); return 1; } FILE *card = fopen(argv[1], "rb"); if (card == NULL) { printf("Could not open file.\n"); return 1; } BYTE buffer[BLOCK_SIZE]; int number_file = 0; char filename[8]; FILE *img = NULL; bool this_first_jpeg = true; while(fread(buffer, BLOCK_SIZE, 1, card) == 1) { printf("while executed\n"); if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] >= 0xe0 && buffer[3] <= 0xef)) { printf("if executed\n"); if (!this_first_jpeg) { fclose(img); } sprintf(filename, "%03i.jpg", number_file++); img = fopen(filename, "wb"); if (img == NULL) { printf("Could not create image file.\n"); fclose(card); return 1; } fwrite(buffer, BLOCK_SIZE, 1, img); this_first_jpeg = false; } else { printf("else executed\n"); if (img != NULL) { fwrite(buffer, BLOCK_SIZE, 1, img); } } } fclose(card); if (img != NULL) { fclose(img); } return 0; }
内容的提问来源于stack exchange,提问作者Pupseg
相关产品推荐
相关产品推荐

