CS50 Week4 Recover作业:000.jpg加载异常排查求助
CS50 Recover作业:000.jpg加载异常的问题修复
你的000.jpg加载异常的核心原因是在找到第一个JPEG文件的起始标记前,就已经向000.jpg写入了内存卡开头的非JPEG数据。
问题代码的核心逻辑缺陷
- 进入循环前,你直接创建并打开了000.jpg文件
- 第一次读取内存卡数据后,若不是JPEG起始块,会执行
else分支的fwrite,把这段无效数据写入000.jpg - 直到找到第一个合法JPEG标记时,000.jpg的头部已经混入了垃圾数据,导致图片无法正常解析
此外还有两个次要问题:
if (argv[1] == NULL)的检查无意义:当argc==2时,argv[1]必然指向传入的参数,不会为NULL- 未处理内存卡文件打开失败的情况:若
fopen返回NULL,后续代码会直接崩溃
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <stdint.h> typedef uint8_t BYTE; int main(int argc, char *argv[]) { // 检查命令行参数数量 if (argc != 2) { fprintf(stderr, "Usage: ./recover IMAGE\n"); return 1; } // 打开内存卡文件并检查是否成功 FILE *card = fopen(argv[1], "r"); if (card == NULL) { fprintf(stderr, "Could not open %s.\n", argv[1]); return 1; } BYTE buffer[512]; int count = 0; FILE *outfile = NULL; char *filename = malloc(8); // 足够存储"000.jpg" + 字符串终止符 while (fread(buffer, sizeof(BYTE), 512, card) == 512) { // 检查JPEG起始标记 if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) { // 如果已有打开的JPEG文件,先关闭 if (outfile != NULL) { fclose(outfile); } // 生成新的JPEG文件名并打开 sprintf(filename, "%03i.jpg", count); outfile = fopen(filename, "w"); if (outfile == NULL) { fprintf(stderr, "Could not create %s.\n", filename); free(filename); fclose(card); return 1; } // 写入当前块 fwrite(buffer, sizeof(BYTE), 512, outfile); count++; } else if (outfile != NULL) { // 仅当正在写入某个JPEG文件时,才继续写入当前块 fwrite(buffer, sizeof(BYTE), 512, outfile); } } // 清理资源 if (outfile != NULL) { fclose(outfile); } fclose(card); free(filename); return 0; }
关键修正说明
- 延迟创建输出文件:初始时
outfile设为NULL,直到找到第一个合法JPEG标记才创建000.jpg,避免写入无效头部数据 - 严格控制写入逻辑:仅当
outfile不为NULL(即正在写入有效JPEG文件)时,才写入非起始块的数据 - 完善错误处理:添加了内存卡文件打开失败的判断,以及输出文件创建失败的回滚逻辑
- 移除无效代码:删除了无意义的
argv[1] == NULL检查
内容的提问来源于stack exchange,提问作者Alok Chedambath
相关产品推荐
相关产品推荐

