【问题标题】:Copying content from one file to another, segmentation fault将内容从一个文件复制到另一个文件,分段错误
【发布时间】:2013-03-19 00:25:53
【问题描述】:

我正在尝试从一个大的 .raw 文件中一张一张地复制 50 个 jpeg,但是目前我遇到了分段错误错误。这是我的代码:

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

typedef uint8_t BYTE;

//SOI - 0xFF 0xD8
//EOI - 0xFF 0xD9
//APPn - 0xFF 0xEn    
int main(void)
{
    //FAT - 512 bytes per block
    BYTE block[512];

    //open file containing pictures
    FILE* card_file = fopen("card.raw", "rd");

    FILE* jpeg_file;

    //make sure the file opened without errors
    if (card_file == NULL)
    {
        printf("something went wrong and file could not be opened");
        return 1;
    }

    int i = 0;
    while (fread(&block, sizeof(BYTE), 512, card_file) != 0)
    {
        //jpeg start signature
        if(block[0] == 0xFF && block[1] == 0xD8)
        {
            i++;
            if(jpeg_file != NULL)
                fclose(jpeg_file);

            //create a new jpeg file to copy bytes to
            jpeg_file = fopen((char*)i, "w+");
        }

        //write 512 bytes to a jpeg file
        if(jpeg_file != NULL)
            fwrite(block, sizeof(block), 1, jpeg_file);
    }

    fclose(card_file);
return 0;
}

当我通过 GDB 运行它时,我的代码一直到 if(block[0] == 0xFF && block1 == 0xD8),然后它会跳过条件并发生分段错误。我看不出是什么原因造成的。 这是一个屏幕截图:

代码更新:

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

typedef uint8_t BYTE;

/*struct jpg*/
/*{*/
/*    BYTE soi[2] = { 0xFF, 0xD8 };*/
/*    BYTE eoi[2] = { 0xFF, 0xD9 };*/
/*};*/

//SOI - 0xFF 0xD8
//EOI - 0xFF 0xD9
//APPn - 0xFF 0xEn    
int main(void)
{
    //FAT - 512 bytes per block
    BYTE block[512];

    //jpeg name
    char name[6];

    bool is_open = false;

    //JPEG
    //struct jpg image;

    //open file containing pictures
    FILE* card_file = fopen("card.raw", "r");

    FILE* jpeg_file;

    //make sure the file opened without errors
    if (card_file == NULL)
    {
        printf("something went wrong and file could not be opened");
        return 1;
    }

    int i = 0;
    while (fread(block, sizeof(BYTE), 512, card_file) != 0)
    {
        //jpeg start signature
        if ((block[0] == 0xFF) && (block[1] == 0xD8) && (block[2] == 0xFF) && ((block[3] == 0xe1) || (block[3] == 0xe0)))
        {
            //assign jpeg name
            sprintf(name, "%d.jpg", i++);
            if(is_open)
                fclose(jpeg_file);

            //create a new jpeg file to copy bytes to
            jpeg_file = fopen(name, "a+");
            is_open = true;
        }

        //write 512 bytes to a jpeg file
        if(is_open)
            fwrite(block, sizeof(block), 1, jpeg_file);
    }

    fclose(jpeg_file);
    fclose(card_file);
return 0;
}

现在它没有崩溃,但是 50 个 jpeg 中只有 9 个被正确恢复。 cs50.h 在那里,所以我可以访问 bool 类型。编写 50 个文件的更好方法是什么?我的布尔值似乎存在逻辑缺陷。

【问题讨论】:

  • 我觉得fopen()不支持rd模式
  • fopen((char*)i, "w+"); wtf?
  • 你还没有初始化jpeg_file
  • 请注意,&lt;stdbool.h&gt; 包含在 "cs50.h" 中,但它是访问类型 bool 的标准方法。

标签: c cs50


【解决方案1】:

fopen((char*)i, "w+"); 完全无效。您将整数转换为指针,这将崩溃。

您需要将数字格式化为文件名:

char path[PATH_MAX];
sprintf(path, "%d", i);
fopen(path, "w+");

您也没有初始化jpeg_file——如果条件失败,jpeg_file 将是一个野指针,它也会崩溃。您应该将jpeg_file 初始化为NULL

【讨论】:

  • 谢谢,我不知道该怎么做。虽然仍然存在段错误。
  • 你能再具体一点吗? jpeg_file 被实例化了,但我不能马上初始化它,因为我需要知道要写什么内容。我能够修复崩溃,但是 50 个文件中只有 9 个被正确恢复。我正在使用当前代码更新我的帖子,如果您能向我展示完成此任务的替代/更好的方法,我将不胜感激。谢谢。
【解决方案2】:

在您的fread 调用中,您应该传递数组的地址。因此,该语句应为fread(block, sizeof(BYTE), 512, card_file)

后记:

  1. 在您的代码中,假设输入文件的大小是 512 的整数倍,而 JPEG 文件不需要这种情况。最后一个 fread 可能会返回一个小于 512 的数字,这需要在您的实现逻辑中进行处理。因此,要写入的元素个数应该由fread的返回值决定

  2. 您需要在循环终止后关闭jpeg_file 指针。

  3. 最后,因为您使用的是 JPEG,您可能需要处理带有缩略图的 EXIF 文件的情况。在这种情况下,您将获得 2 个 SOI(图像开始)标记。

【讨论】:

  • 这是一个班级的问题集。根据说明,我认为文件是 FAT 格式,所有 jpeg 都从内存块的开头开始。关闭 jpeg_file 绝对是我添加的,谢谢,但在这种情况下并不重要,文件会自动关闭,至少这是我读到的。你说的第3点是什么意思?你能举个例子吗? ------ 在进行所有更改后,我仍然崩溃。我还注意到我的前 2 个十六进制字节是 0,我读错了吗?我添加了 printf("%X %X\n", block[0], block[1]);检查值
  • @user1937588 您是否修改了fread 语句以删除block 后面的&amp;?即使在此更改之后,您是否观察到崩溃?第 3 点与 EXIF 文件有关,您将在该文件中嵌入一个缩略图和主图像。如果您不熟悉 JPEG 处理,请忽略此评论。您能否也分享一下自动关闭文件的参考?
  • 1) 关于文件,在“Programming in C”一书,第 2 版,在处理 I/O 的章节中提到。作者表示,一旦您的程序运行完毕,文件就会由操作系统自动关闭,但他鼓励读者手动关闭它们。 2)我修复了代码,它可以按我的需要工作而不会崩溃,它会检索所有 jpeg。我只是想知道替代代码/更有效的解决方案。
  • 另外,FAT 的结构方式是,jpeg 总是从 512 字节块的开头开始。老师讲解截图如下:snag.gy/RaUiJ.jpg
  • @user1937588 我认为您当前的代码很好。关于文件关闭,始终建议在离开函数/范围之前显式关闭文件,以确保您没有机会让系统为您关闭它。这是推荐的编程实践。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-24
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 2015-07-17
  • 2011-06-04
相关资源
最近更新 更多