You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从.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);

其他潜在问题修复

  1. 栈溢出风险: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);
  1. 循环越界:外层循环条件while (i<=size_bytes/512)改为while (i < size_bytes/512),避免访问超出数组范围的元素。

  2. 内层循环边界判断:内层循环中j可能超过文件块总数,添加判断:

while (j < size_bytes/512)
  1. 二进制文件打开模式:打开.raw文件和JPEG文件时,使用rb和wb模式,避免Windows系统下的换行符自动转换:
FILE *card=fopen(argv[1],"rb");
FILE *image=fopen(buff,"wb");

内容的提问来源于stack exchange,提问作者Nierdo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:16:00