首页 > 解决方案 > 我的代码出现分段错误

问题描述

我正在编写一个从存储卡中读取信息的代码(card.raw 是我们提供的,但代码使用用户输入)并使用 jpeg 具有的签名从中提取 jpegs (0xff,0xd8,0xff,0x00 - 0xff)。我遇到了分段错误,因为我使用的是 malloc,但我看不出哪里出错了。我在这里粘贴我的代码,任何帮助将不胜感激。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>


typedef uint8_t BYTE;

int main(int argc, char *argv[])
{
    //check terminal usage
    if (argc != 2)
    {
        printf("Usage: ./recover image");
        return 1;
    }

    //open inputted file and check for valid file
    FILE *file = fopen(argv[1], "r");
    if (!file)
    {
        printf("Invalid or missing file.");
        return 1;
    }

    BYTE *buff = malloc(512 * sizeof(BYTE));
    int counter = 0;
    FILE *image = NULL;
    char *name = malloc(8 * sizeof(char));

    //loop till end of file reached and read a block of input
    while(fread(buff, sizeof(BYTE), 512, file) == 1 && !feof(file))
    {
        bool foundJPEG = buff[0] == 0xff && buff[1] == 0xd8 && buff[2] == 0xff && ((buff[3] & 0xf0) == 0xe0);

        //check if found jpeg, and open file for writing
        if (foundJPEG)
        {
            sprintf(name, "%03i.jpg", counter);
            image = fopen(name, "w");
        }
        //if image file open, write to it
        if (image != NULL)
        {
            fwrite(buff, sizeof(BYTE), 512, image);
        }
        //if found a jpeg already, close it so new one can be written
        if (foundJPEG && image != NULL)
        {
            fclose(image);
            counter++;
        }

    }

    free(name);
    free(buff);
    fclose(image);
    fclose(file);
    return 0;

}

标签: ccs50

解决方案


上面的代码存在三个问题,注释中没有提到:

读取成功后,返回值fread不是 1 而是 512。您交换了 blocksize 和 blockcount -> fread 定义的参数。因此不进入while循环。不要试图通过将大量代码打包到一个语句中来节省空间。如果将返回值和 EOF 的检查分开fread并使用do ... while()循环会更聪明。然后你有机会在调试器中看到这个问题。这正是我所做的以及我是如何发现这一点的。

第二个问题是您在抢救前 512 个字节后关闭了图像,但您没有将文件指针image与语句NULL一起重置。fclose结果,代码将重复写入一个关闭的文件,直到找到一个带有 jpg 标头的新块。

第三个问题是你只拯救了 jpg 的前 512 个字节,而不是整个 jpg。您需要扫描输入流中的 jpg 结束指示符FF D9并复制字节,直到找到为止。-> jpg 格式


推荐阅读