CS50恢复-为什么我总是遇到分段错误?

CS50恢复-为什么我总是遇到分段错误?,c,segmentation-fault,cs50,recover,C,Segmentation Fault,Cs50,Recover,我是一个完全的编程初学者,我真的不明白哪里出了错。我看了别人的代码,修改了很多东西,但都没用:如果有任何帮助,我将不胜感激 #include <stdio.h> #include <stdlib.h> #include <stdint.h> int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage ./recover image\n"

我是一个完全的编程初学者,我真的不明白哪里出了错。我看了别人的代码,修改了很多东西,但都没用:如果有任何帮助,我将不胜感激

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

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

    FILE *card = fopen(argv[1], "r");

    if (card == NULL)
    {
        printf("ERROR\n");
        return 1;
    }

    int jpeg_num = 0;
    typedef uint8_t BYTE;
    BYTE buffer[512];
    char filename[10];
    FILE *image = NULL;

    while (fread(buffer, sizeof(BYTE), 1, card) == 1)
    {
        if (buffer[0] == 0xff && buffer[1] == 0xd0 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {

            if (jpeg_num > 0)
            {
                fclose(image);
            }

            sprintf(filename, "%03i.jpeg", jpeg_num);
            image = fopen(filename, "w");
            fwrite(buffer, sizeof(BYTE), 1, image);
            jpeg_num++;
        }

        else
        {
            fwrite(buffer, sizeof(BYTE), 1, image);
        }
    }

    fclose(image);
    fclose(card);
    return 0;
}
#包括
#包括
#包括
int main(int argc,char*argv[])
{
如果(argc!=2)
{
printf(“用法/恢复图像\n”);
返回1;
}
文件*card=fopen(argv[1],“r”);
如果(卡==NULL)
{
printf(“错误\n”);
返回1;
}
int jpeg_num=0;
typedef uint8_t字节;
字节缓冲区[512];
字符文件名[10];
文件*image=NULL;
while(fread(缓冲区,sizeof(字节),1,卡)=1)
{
如果(缓冲区[0]==0xff&&buffer[1]==0xd0&&buffer[2]==0xff&&buffer[3]&0xf0)==0xe0)
{
如果(jpeg_num>0)
{
fclose(图像);
}
sprintf(文件名,“%03i.jpeg”,jpeg\u num);
image=fopen(文件名,“w”);
fwrite(缓冲区,大小(字节),1,图像);
jpeg_num++;
}
其他的
{
fwrite(缓冲区,大小(字节),1,图像);
}
}
fclose(图像);
信用卡;
返回0;
}

CS50使用地址消毒剂(
-fsanize=address
)编译程序,对吗?如果是这样,您应该收到如下信息:

ASAN:DEADLYSIGNAL
=================================================================
==4179==错误:地址消毒器:未知地址0x000000000000上的SEGV(pc 0x7f280eabf92e bp 0x000000000001 sp 0x7fffc6e02bd0 T0)
==4179==该信号是由读取内存访问引起的。
==4179==提示:地址指向零页。
#写入(/lib/x86\u 64-linux-gnu/libc.so.6+0x7f92d)中的0 0x7f280eabf92d
#1 0x7f281020107f位于主/../a.c:45中
#2个0x7f280ea61b96,位于libc\u start\u main(/lib/x86\u 64-linux-gnu/libc.so.6+0x21b96)中
#3 0x7f2810200c79在_开始(/…/a+0xc79)
AddressSanitizer无法提供其他信息。
摘要:AddressSanitizer:SEGV(/lib/x86_64-linux-gnu/libc.so.6+0x7f92d)在_IO_fwrite中
==4179==中止
(这是来自
gcc
而不是
clang
,但是
clang
的地址消毒剂应该给出类似的结果。)

所以您尝试从地址0读取。这可能是
NULL
或初始化的指针。我们甚至知道它发生在第45行对
fwrite
的调用中

有两个指针被传递到
fwrite
buffer
image
buffer
是一个自动分配的数组,因此它是一个有效的指针<另一方面,代码>图像
初始化如下:

FILE*image=NULL;

在调用
fwrite
失败之前,是否可能从未更改?对这很糟糕。

如果通过调试器运行代码,它应该会在发生segfault的准确行上停止(这可能不是错误所在的同一行,但如果您在该点检查某些变量的值,您应该能够从上下文中找出它。)
fread(缓冲区,大小(字节),1,卡)
仅读取一个字节,但您正在检查缓冲区中的其他字节。始终从
fread
捕获返回值,以便知道要写入多少。
fwrite(buffer,sizeof(BYTE),1,image)可以/将针对此代码中的
NULL
图像文件指针触发。如果If子句至少未满足一次,
image
将为null,并且该代码调用未定义的行为。感谢您的帮助!我了解问题所在,但在编写之前我应该在哪里/如何更改它?抱歉,我只是不知道我需要添加什么:/