从.raw文件恢复JPEG时遇glibc无效stdio handle错误求排查
解决从.raw文件恢复JPEG时的"glibc detected an invalid stdio handle"错误
问题现象
编写.raw文件图像恢复程序时触发以下错误:
glibc detected an invalid stdio handle aborted
错误发生在创建JPEG文件指针、写入数据后调用fclose时,已确认image指针不为NULL,站内同类问题均不匹配当前场景。
编译器完整输出:
Fatal error: glibc detected an invalid stdio handle
Aborted (core dumped)
问题代码
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef unsigned char BYTE; int main(int argc, char *argv[]) { if (argc!=2) { printf("Invalid Argument Count!\n"); return 1; } FILE *card=fopen(argv[1],"r"); if (card==NULL) { printf("%s Could Not Be Read!\n",argv[1]); return 2; } //get size fseek(card,0,SEEK_END); int size_bytes=ftell(card); //assuming FAT filesystem int block_starts[size_bytes/512]; for (int i=0;i<size_bytes/512;i++) { block_starts[i]=i*512; } int i=0; int k=0; int j; BYTE *signature=malloc(4*sizeof(BYTE)); BYTE *signature_2=malloc(4*sizeof(BYTE)); char buff[8]; if ((signature==NULL)||(signature_2==NULL)) { printf("Not Enough Memory!\n"); return 3; } //JPEG condition while (i<=size_bytes/512) { j=i+1; fseek(card,block_starts[i],SEEK_SET); fread(signature,sizeof(BYTE),4,card); if ((*signature==0xff)&&(*(signature+1)==0xd8)&&(*(signature+2)==0xff)&&(0xe0<=*(signature+3))&&(*(signature+3)<=0xef)) { while (true) { fseek(card,block_starts[j],SEEK_SET); fread(signature_2,sizeof(BYTE),4,card); if((*signature==0xff)&&(*(signature+1)==0xd8)&&(*(signature+2)==0xff)&&(0xe0<=*(signature+3))&&(*(signature+3)<=0xef)) { fseek(card,block_starts[i],SEEK_SET); sprintf(buff,"%03i.jpg",k); FILE *image=fopen(buff,"w"); if (image==NULL) { printf("%s Could Not Be Created!\n",buff); return 1; } fread(image,sizeof(BYTE),(j-i)*512,card); fclose(image); k++; i=j; break; } else { j++; } } } else { i++; } } fclose(card); free(signature); free(signature_2); return 0; }
错误原因及修复
核心错误:误用fread函数
代码中第60行的fread(image,sizeof(BYTE),(j-i)*512,card);完全错误:
fread的作用是从文件读取数据到缓冲区,第一个参数必须是内存缓冲区指针,而非输出文件指针- 要把.raw文件的数据写入JPEG文件,需先将数据读到缓冲区,再用
fwrite写入目标文件
修改该段代码为:
fseek(card,block_starts[i],SEEK_SET); sprintf(buff,"%03i.jpg",k); FILE *image=fopen(buff,"wb"); // 用二进制模式打开,避免格式转换 if (image==NULL) { printf("%s Could Not Be Created!\n",buff); return 1; } // 分配缓冲区存储要写入的数据 BYTE *buffer = malloc((j-i)*512); if (buffer == NULL) { printf("Memory allocation failed!\n"); fclose(image); return 4; } // 从raw文件读取数据到缓冲区 fread(buffer, sizeof(BYTE), (j-i)*512, card); // 将缓冲区数据写入JPEG文件 fwrite(buffer, sizeof(BYTE), (j-i)*512, image); // 释放缓冲区并关闭文件 free(buffer); fclose(image);
其他潜在问题修复
- 栈溢出风险:
int block_starts[size_bytes/512];若.raw文件过大会导致栈溢出,改为动态分配:
int *block_starts = malloc((size_bytes/512) * sizeof(int)); if (block_starts == NULL) { printf("Not Enough Memory!\n"); return 3; } // 使用完后记得释放 free(block_starts);
循环越界:外层循环条件
while (i<=size_bytes/512)改为while (i < size_bytes/512),避免访问超出数组范围的元素。内层循环边界判断:内层循环中
j可能超过文件块总数,添加判断:
while (j < size_bytes/512)
- 二进制文件打开模式:打开.raw文件和JPEG文件时,使用
rb和wb模式,避免Windows系统下的换行符自动转换:
FILE *card=fopen(argv[1],"rb"); FILE *image=fopen(buff,"wb");
内容的提问来源于stack exchange,提问作者Nierdo
相关产品推荐
相关产品推荐

