CS50 Recover(Pset4)程序出现段错误,无法生成50张JPEG图片
CS50 Pset4 Recover 问题修复
段错误根源
程序启动时img初始化为NULL,在找到第一个JPEG之前,else分支会执行fwrite往空指针写入数据,直接触发段错误。
灰白棋盘格/图片损坏原因
- 文件名计数错误:你从
count=1开始生成文件名(001.jpg),但测试数据里的JPEG是从000.jpg开始的,导致文件顺序完全错位,后续数据写入到错误文件中。 - 未以二进制模式操作文件:用
"w"打开文件会在部分系统(如Windows)中自动转换换行符,破坏JPEG的二进制结构。 - 最后一个文件未关闭:循环结束后未关闭
img文件,部分数据未刷入磁盘,导致文件损坏。 - 漏处理末尾不足512字节的数据:原循环只处理完整的512字节块,最后一个JPEG的剩余字节未被写入。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <stdint.h> const int BLOCK_SIZE = 512; int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: ./recover IMAGE\n"); return 1; } FILE *card = fopen(argv[1], "rb"); if (card == NULL) { printf("Error! File cannot be opened\n"); return 1; } typedef uint8_t block; block store[BLOCK_SIZE]; int count = 0; char filename[8]; FILE *img = NULL; // 处理完整的512字节块 while (fread(store, 1, BLOCK_SIZE, card) == BLOCK_SIZE) { if (store[0] == 0xff && store[1] == 0xd8 && store[2] == 0xff && ((store[3] & 0xf0) == 0xe0)) { // 若已有打开的图片文件,先关闭 if (img != NULL) { fclose(img); } // 生成从000开始的文件名 sprintf(filename, "%03i.jpg", count); img = fopen(filename, "wb"); fwrite(store, 1, BLOCK_SIZE, img); count++; } else if (img != NULL) { // 仅当图片文件已打开时,写入数据 fwrite(store, 1, BLOCK_SIZE, img); } } // 处理剩余不足512字节的数据 size_t remaining = fread(store, 1, BLOCK_SIZE, card); if (img != NULL && remaining > 0) { fwrite(store, 1, remaining, img); } // 关闭所有打开的文件 if (img != NULL) { fclose(img); } fclose(card); return 0; }
关键修复点
- 添加
img != NULL判断,避免空指针写入操作。 - 计数从0开始,确保文件名匹配测试数据的
000.jpg到049.jpg。 - 使用
"rb"和"wb"模式操作二进制文件,避免数据格式转换错误。 - 循环结束后处理剩余字节,并关闭所有打开的文件。
内容的提问来源于stack exchange,提问作者PianoOwl
相关产品推荐
相关产品推荐

