CS50第四周JPEG恢复C代码出现未知段错误,求技术帮助
修复CS50 JPEG恢复程序的段错误及逻辑问题
你的程序出现段错误和功能异常,核心问题集中在以下几点:
未检查文件打开结果
打开输入文件后没有判断返回的文件指针是否为NULL,如果文件不存在或无权限访问,后续fread操作会访问空指针,直接触发段错误。添加检查:FILE *f = fopen(argv[1], "rb"); if (f == NULL) { printf("无法打开输入文件\n"); return 1; }fread参数使用错误
fread的参数逻辑是(缓冲区, 单个元素大小, 元素数量, 文件指针)。你原来的代码fread(&b, sizeof(b), sizeof(b), f)会尝试读取4个4字节的元素(共16字节),完全偏离了“读取4字节检测JPEG头”的需求,还会导致文件指针跳转过快,引发内存访问问题。正确写法:// 每次读取4字节,判断是否成功读取全部4字节 while (fread(b, 1, sizeof(b), f) == sizeof(b)) {另外,数组名
b本身就是指向首元素的指针,不需要加&。JPEG写入逻辑不完整
当前代码找到JPEG头后只写入一个512块就关闭文件,但JPEG由连续的512块组成,直到下一个JPEG头或文件结束。而且你还漏掉了把检测到的JPEG头写入文件(因为fread已经把这4字节读出来了)。修复后的写入逻辑:filecounter++; char filename[10]; snprintf(filename, sizeof(filename), "%03i.jpg", filecounter); FILE *img = fopen(filename, "wb"); if (img == NULL) { printf("无法创建图片文件\n"); fclose(f); return 1; } // 先写入刚才检测到的JPEG头 fwrite(b, 1, sizeof(b), img); BYTE BLOCK[512]; size_t bytes_read; while (1) { bytes_read = fread(BLOCK, 1, sizeof(BLOCK), f); if (bytes_read == 0) break; // 文件结束 // 检查当前块是否是新的JPEG头 if (BLOCK[0] == 0xff && BLOCK[1] == 0xd8 && BLOCK[2] == 0xff && (BLOCK[3] & 0xf0) == 0xe0) { // 回退4字节,留给下一次循环检测 fseek(f, -4, SEEK_CUR); break; } fwrite(BLOCK, 1, bytes_read, img); } fclose(img);使用文本模式操作二进制文件
Windows系统中,"r"/"w"模式会自动转换换行符,破坏JPEG的二进制结构。必须用"rb"(读二进制)和"wb"(写二进制)模式打开文件。用snprintf替代sprintf提升安全性
sprintf存在缓冲区溢出风险,snprintf可以指定写入的最大字节数,避免意外溢出。
内容的提问来源于stack exchange,提问作者greec_d
相关产品推荐
相关产品推荐

