CS50恢复分段故障问题

CS50恢复分段故障问题,c,segmentation-fault,cs50,C,Segmentation Fault,Cs50,该程序的目标是从文件中恢复JPGs 在CS50在线课程中,我研究这个问题已经有四五天了,我就是想不出来。我继续得到分割错误,我不知道为什么 我尝试了debug50,发现当程序试图写入新文件时,我出现了错误。我不明白为什么会这样 这一次我的头撞到墙上,我已经完全抹掉并重写了好几次。任何帮助都将不胜感激 #include <stdio.h> #include <stdlib.h> #include <stdint.h> int main(int argc, ch

该程序的目标是从文件中恢复JPGs

在CS50在线课程中,我研究这个问题已经有四五天了,我就是想不出来。我继续得到分割错误,我不知道为什么

我尝试了debug50,发现当程序试图写入新文件时,我出现了错误。我不明白为什么会这样

这一次我的头撞到墙上,我已经完全抹掉并重写了好几次。任何帮助都将不胜感激

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

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage ./recover file.type\n");
        return 1;
    }

    char *infile = argv[1];
    FILE *inptr = fopen(infile, "rb");


    if (inptr == NULL)
    {
        fprintf(stderr, "Could not open file designated to be recovered\n");
        fclose(inptr);
        return 2;
    }

    int counter = 0;
    FILE *img;

    uint8_t buffer[512];

    while (fread(buffer, sizeof(*buffer), 512, inptr))
    {
        if (buffer[0] == 0xff &&
            buffer[1] == 0xd8 &&
            buffer[2] == 0xff &&
            (buffer[3] & 0xf0) == 0xe0)
        {
            if (counter > 0)
            {
                fclose(img);
            }

            char filename[8];
            sprintf(filename, "%03i.jpg", counter);

            img = fopen(filename, "w");

            counter++;
        }

        if (counter !=0)
        {
            fwrite(buffer, sizeof(*buffer), 512, img);
        }
    }
    fclose(img);
    fclose(inptr);
    return 0;
}
#包括
#包括
#包括
int main(int argc,char*argv[])
{
如果(argc!=2)
{
fprintf(stderr,“用法./recover file.type\n”);
返回1;
}
char*infle=argv[1];
文件*inptr=fopen(填充“rb”);
如果(inptr==NULL)
{
fprintf(stderr,“无法打开指定要恢复的文件”\n);
fclose(inptr);
返回2;
}
int计数器=0;
文件*img;
uint8_t缓冲器[512];
while(fread(缓冲区,sizeof(*缓冲区),512,inptr))
{
如果(缓冲区[0]==0xff&&
缓冲区[1]==0xd8&&
缓冲区[2]==0xff&&
(缓冲区[3]&0xf0)==0xe0)
{
如果(计数器>0)
{
fclose(img);
}
字符文件名[8];
sprintf(文件名为“%03i.jpg”,计数器);
img=fopen(文件名,“w”);
计数器++;
}
如果(计数器!=0)
{
fwrite(缓冲区,sizeof(*缓冲区),512,img);
}
}
fclose(img);
fclose(inptr);
返回0;
}
由于NUL终止符
\0
,七个字符的字符串占用8个字符。使数组变大,这样就不会写过数组的末尾

if(img == NULL)
{
    fprintf(stderr, "Could not create image file\n");
    fclose(img);
    return 3;
}

如果
img
未打开,则无需关闭它。另一方面,如果它确实打开了,那么您确实需要关闭它。将
fclose()
调用移动到循环的末尾。

好的,所以我发现我在上一个if语句中输入的不是运算符,而我应该输入的是:

    if (counter != 0)
    {
        fwrite(buffer, sizeof(buffer), 1, img);
    }
然而,我仍然对程序返回分段错误的原因感到困惑

我的理解是,当程序到达这个特定的if语句时,它将不会执行,因为计数器的计算结果将为false

在读取返回0的整个输入文件后,程序不就结束了吗

分段错误从何而来?

除了答案

查看
fwrite
函数的语法:

根据文档,
size
参数是
缓冲区中每个值的大小

在代码中,您有:

fwrite(buffer, 512, 1, img);
问题是显而易见的

看起来您对
fread
也这样做。函数的语法为:

在代码中,您可以执行以下操作:

fread(buffer, 512, 1, inptr)
但应该是这样

fread(buffer, sizeof *buffer, 512, inptr)

另外,在处理此类文件时,我建议以二进制模式打开它们,以免篡改正在读取的数据

FILE *inptr = fopen(infile, "rb");


最后,您应该使用
fread
的返回值,它告诉您实际读取的字节数。然后,您可以在
fwrite
中使用此值来确保写入的字节数正确。

我不太理解您对fclose()函数调用的看法。你能澄清一下吗?如果
img==NULL
那么你不应该调用
fclose(img)
,因为你只是在传递一个
NULL
指针。文件未成功打开,因此不要试图关闭它。相反,当您处理完文件时,应该在
while
循环的末尾调用
fclose(img)
,但该调用丢失了。在循环结束后,您有一个对
fclose()
的调用,但它实际上应该在最后的循环中。我已经对代码实现了本线程中提到的更改,但仍然存在分段错误。只有将fclose()调用移到while循环之外,故障才会消失。我完全糊涂了。我做错了什么?好吧,这很有道理。然而,我发现,在更改名称字符串中的字符数并更改我所描述的最后一个if语句后,我能够交换fwrite和fread中的数字,并且程序仍然成功运行。这里还有什么我遗漏的吗?@zachdalton,成功运行并不意味着它是正确的。例如,如果查看
fwrite
的文档,您会发现它没有检查数组的大小,它所关心的只是将大小为
size
的对象写入缓冲区。在你的例子中,它工作是因为它将大小为
512
字节的
1
对象写入你的数组,而你的数组正好工作,因为你的数组可以占用
512
字节。我明白了。我显然有很多东西要学。我感谢你的帮助。我觉得当我在学习这一切的时候,我错过了很多我应该学习的细微差别和更好的地方。@zachdalton,yw。不用担心,它很快就会成为第二天性。交换大小和计数参数不会破坏任何东西。它们是可互换的。分割错误发生在哪里?使用
-g
标志编译程序,然后使用
gdb
运行二进制文件。这将告诉您分段错误发生的位置
!计数器
计数器!=0是等效表达式。他们做完全相同的事情。这只是巧合,当你改变那条线时,行为发生了变化。这是我在观看使用操作符的讲座后最初的想法。另一个教程让我很困惑,因为在我换了它之后它就起作用了,所以我认为我错了。
fread(buffer, 512, 1, inptr)
fread(buffer, sizeof *buffer, 512, inptr)
FILE *inptr = fopen(infile, "rb");