分段错误:CS50 recover.c

分段错误:CS50 recover.c,c,cs50,C,Cs50,此程序接受文件名作为输入,并应恢复该文件上的所有JPEG。它一次读取512字节,检查新jpeg的开始 当我运行程序时,它会编译,但它会出现分段错误。请告诉我如何着手解决这个问题 #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { // check for proper usage if (argc != 2) { printf("Usa

此程序接受文件名作为输入,并应恢复该文件上的所有JPEG。它一次读取512字节,检查新jpeg的开始

当我运行程序时,它会编译,但它会出现分段错误。请告诉我如何着手解决这个问题

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

int main(int argc, char *argv[])
{
    // check for proper usage
    if (argc != 2)
    {
        printf("Usage: 1 command line argument\n");
        return 1;
    }

    // check if file can be opened
    FILE *file = fopen(argv[1], "r");
    if (file == NULL)
    {
        printf("Cannot be opened\n");
        return 2;
    }

    // read 512 bytes into buffer until end of card
    int buffer[128];
    int counter;
    counter = 0;
    char filename[8];
    FILE *img = NULL;

    while(fread(buffer, 4, 128, file) == 128)
    {
        //check if start of new JPEG
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            //check if first JPEG
            if (counter == 0)
            {
                sprintf(filename, "%03i.jpg", counter);
                img = fopen(filename, "w");
                fwrite(buffer, 4, 128, img);
                counter += 1;
            }
            else if (counter > 0)
            {
                fclose(img);
                sprintf(filename, "%03i.jpg", counter);
                img = fopen(filename, "w");
                fwrite(buffer, 4, 128, img);
                counter += 1;
            }
        }
        else if (counter > 0)
        {
            fwrite(buffer, 4, 128, img);
        }
    }
    fclose(img);
    fclose(file);
    return 0;
}
#包括
#包括
int main(int argc,char*argv[])
{
//检查是否正确使用
如果(argc!=2)
{
printf(“用法:1命令行参数\n”);
返回1;
}
//检查文件是否可以打开
FILE*FILE=fopen(argv[1],“r”);
if(file==NULL)
{
printf(“无法打开\n”);
返回2;
}
//将512字节读入缓冲区,直到卡结束
int缓冲区[128];
整数计数器;
计数器=0;
字符文件名[8];
文件*img=NULL;
while(fread(缓冲区,4128,文件)==128)
{
//检查是否启动新的JPEG
如果(缓冲区[0]==0xff&&buffer[1]==0xd8&&buffer[2]==0xff&&buffer[3]&0xf0)==0xe0)
{
//检查是否为第一个JPEG
如果(计数器==0)
{
sprintf(文件名为“%03i.jpg”,计数器);
img=fopen(文件名,“w”);
fwrite(缓冲区,4128,img);
计数器+=1;
}
否则如果(计数器>0)
{
fclose(img);
sprintf(文件名为“%03i.jpg”,计数器);
img=fopen(文件名,“w”);
fwrite(缓冲区,4128,img);
计数器+=1;
}
}
否则如果(计数器>0)
{
fwrite(缓冲区,4128,img);
}
}
fclose(img);
fclose(文件);
返回0;
}
fclose(img)
是罪魁祸首<代码>img为空。为了找出原因,您可以在
fopen
之后插入一些
printf
。下面是将来调试任何SEGFULTS的方法

$ ./recover card.raw

  Memory access error: invalid parameter; abort execution.
  # fclose's parameter (0x0) is not a valid FILE pointer.
  # Stack trace (most recent call first) of the error.
  # [0]  file:/recover.c::55, 5
  # [1]  [libc-start-main]
fclose(img)
是罪魁祸首<代码>img为空。为了找出原因,您可以在
fopen
之后插入一些
printf
。下面是将来调试任何SEGFULTS的方法

$ ./recover card.raw

  Memory access error: invalid parameter; abort execution.
  # fclose's parameter (0x0) is not a valid FILE pointer.
  # Stack trace (most recent call first) of the error.
  # [0]  file:/recover.c::55, 5
  # [1]  [libc-start-main]
调用
fread(buffer,4128,file)
将512字节读入128个整数的数组中。但是,当您随后在此代码中测试新JPEG文件的开始时:

if(buffer[0]==0xff&&buffer[1]==0xd8&&buffer[2]==0xff&&buffer[3]&0xf0)==0xe0)
{
//...
您正在检查数组中前四个整数中每个整数的低位字节,而不是(应该)检查数组的前四个字节。这四个字节都将位于前四个整数元素(
buffer[0]
)中

因此,您的程序将永远无法找到新JPEG的开头,因此,
img
文件将永远无法打开……然后您将使用
NULL
文件指针调用
fclose
,这是未定义的行为,可能会导致您看到的分段错误

相反(假设“endianness”正确),请执行以下检查:

if((缓冲区[0]&0xfffffff0)=0xFFD8FF0)
{
//... 
要考虑到“错误的endianness”,您可以检查
缓冲区[0]
中的任一字节顺序:

if((缓冲区[0]&0xFFFFF0)==0xFFD8FF0 | |(缓冲区[0]&0xFFFFFF)==0xe0ffd8ff)
{
//... 
更好的是,只需读取(和写入)缓冲区,即512字节的数组,代码如下:

无符号字符缓冲区[512];
//...
while(fread(缓冲区,1512,文件)==512)
{
//...
这样,您就可以保持“JPEG开始”测试的原样。

调用
fread(buffer,4128,file)
将512字节读入128个整数的数组中(正如您正确地说的那样)。但是,当您在该代码中测试新JPEG文件的开始时:

if(buffer[0]==0xff&&buffer[1]==0xd8&&buffer[2]==0xff&&buffer[3]&0xf0)==0xe0)
{
//...
您正在检查数组中前四个整数中每个整数的低位字节,而不是(应该)检查数组的前四个字节。这四个字节都将位于前四个整数元素(
buffer[0]
)中

因此,您的程序将永远无法找到新JPEG的开头,因此,
img
文件将永远无法打开……然后您将使用
NULL
文件指针调用
fclose
,这是未定义的行为,可能会导致您看到的分段错误

相反(假设“endianness”正确),请执行以下检查:

if((缓冲区[0]&0xfffffff0)=0xFFD8FF0)
{
//... 
要考虑到“错误的endianness”,您可以检查
缓冲区[0]
中的任一字节顺序:

if((缓冲区[0]&0xFFFFF0)==0xFFD8FF0 | |(缓冲区[0]&0xFFFFFF)==0xe0ffd8ff)
{
//... 
更好的是,只需读取(和写入)缓冲区,即512字节的数组,代码如下:

无符号字符缓冲区[512];
//...
while(fread(缓冲区,1512,文件)==512)
{
//...

这样,您就可以保持“JPEG start”测试的原样。

谢谢,这个解释真的帮了大忙。我做了必要的更改,程序现在运行得很顺利。谢谢,这个解释真的帮了大忙。我做了必要的更改,程序现在运行得很顺利。