CS50&#ps4上的分段错误

时间:2017-03-17 20:51:56

标签: c terminal segmentation-fault cs50

我正在疯狂地试图找出我的代码发生了什么。

我目前在CS50的pset4中。恢复挑战。

对于那些不知道它是什么的人: 我们给了一个名为card.raw的文件,其中有一些已删除的照片。我们的任务是实现一个程序,可以做一些取证(idyllically)和恢复丢失的照片。

我附上我的代码:

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


int main(int argc, char *argv[])
{
    if (argc != 2)
    {

        fprintf(stderr, "Usage: ./recover file\n");
        return 1;
    }

    //declaring pointer infile and giving the address of argv[1];
    char *infile = argv[1];

    //Opening file
    FILE *raw_data; 
    raw_data = fopen(infile, "r");

    //Checking for NULL error
    if(raw_data == NULL)
    {
        fprintf(stderr, "Could not open file.\n");
        return 2;
    }


    uint8_t buffer[512];                //Delcaring unsigned int variable type. Array of 512 bytes.
    int counter = 0;                    //Declaring counter for counting jpegs files

    FILE *outfile;                    //Setting pointer named outfile for printing here

    char filename[8];                 //declaring 'filename' variable for storing the file's name


    //While we can reads blocks of memory of 512 bytes from raw_data (aka the address from the infile) into buffer:
    while (fread(buffer, 512, 1, raw_data))
    {
        //Condition for tracking the first bytes that form a JPEG file
        if(buffer[0] == 0xff && 
           buffer[1] == 0xd8 && 
           buffer[2] == 0xff &&
          (buffer[3] & 0xf0) == 0xe0)
          {


              if(counter == 0)                              //If this is the 1st file, then name the file with 
                                                            //counter value with 3 digits (%03d)
              {                                             
                  sprintf(filename, "%03d.jpg", counter);   // And 3 digits (%i3)
                  outfile = fopen(filename, "w");           //Open file named outfile in write mode
                  counter++;
              }

              else                              //If this is not the first JPG opened, firstly close the 
              {                                 // current open file, and then open a new one with the 
                  fclose(outfile);              // current counter value and 3 digits for its name
                  sprintf(filename, "%03d.jpg", counter);
                  outfile = fopen(filename, "w");   //Open file named 'outfile' in write mode 
                  counter++;

              }


          }

        fwrite(buffer, 1, sizeof(buffer), outfile); /* Write function that takes buffer data (aka the 
                                                       pointer to the array of elements to be written, 
                                                       writes 1 byte of elements of the syze buffer (512)
                                                       and it writes it to the output, aka 'outfile' */
    }
    fclose(outfile);            //Remember to close the last file once we get out of the while-loop
}

这是一个棘手的部分:

我已经成功恢复了所有问题图片。 但是,如果我多次运行代码,比如说5次,我最终会出现分段错误。

当我运行check50时,我收到以下消息(在一些成功运行和check50 veredict之后,我将附加一个包含分段错误的图像)。 Click here to see the image

我无法得到它。我觉得记忆可能有些麻烦,但我不知道它是什么。

非常感谢您的时间和帮助。 StackOVerFlow总是一个寻求指导的好地方。

修改

如果在提示分段错误后运行echo $?,则值为139.

Here's the terminal prompt screenshot

修改

正如@Thomas Dickey指出的那样,该程序正在写一个文件,无论是否有一个打开的文件。

我已经更新并修复了一些我的代码以保持清洁,并添加了if条件以便修复它。

以下是解决方案:

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


int main(int argc, char *argv[])
{
if (argc != 2)
{

    fprintf(stderr, "Usage: ./recover file\n");
    return 1;
}

//declaring pointer infile and giving the address of argv[1];
char *infile = argv[1];

//Opening file
FILE *raw_data; 
raw_data = fopen(infile, "r");

//Checking for NULL error
if(raw_data == NULL)
{
    fprintf(stderr, "Could not open file.\n");
    return 2;
}

uint8_t buffer[512];                //Delcaring unsigned int variable type. Array of 512 bytes.

int counter = 0;                    //Declaring counter for counting jpegs files

FILE *outfile;                    //Setting pointer named outfile for printing here

char filename[8];                 //declaring 'filename' variable for storing the file's name


//While we can reads blocks of memory of 512 bytes from raw_data (aka the address from the infile) into buffer:
while (fread(buffer, 512, 1, raw_data))
{
    //Condition for tracking the first bytes that form a JPEG file
    if(buffer[0] == 0xff && 
       buffer[1] == 0xd8 && 
       buffer[2] == 0xff &&
      (buffer[3] & 0xf0) == 0xe0)
      {

          if(counter != 0)                              
          {           
              fclose(outfile);                      //If this is not the first JPG opened, close previous file
          }

          sprintf(filename, "%03d.jpg", counter);  //print stream to 'filename' the value of 'counter' in 3 digits  
          outfile = fopen(filename, "w");           //Open file named outfile in write mode
          counter++;                                //Add 1 to counter

      } 
      if(counter != 0)                          //Don't start writing on a file until the first jpeg is found
      {
        fwrite(buffer, sizeof(buffer), 1, outfile);          /* - Write function that takes buffer data
                                                                    (aka the array of elements to be written) , 
                                                                - Write a block of 512 bytes of elements 
                                                                    (aka the size of buffer), 
                                                                - 1 block of 512 bytes at a time, 
                                                                - And it writes it to the output, aka 'outfile' */
      }                                                         

}
fclose(outfile);            //Remember to close the last file once we get out of the while-loop
return 0;

}

1 个答案:

答案 0 :(得分:2)

如果标题看起来没问题,程序只会打开输出文件,但无论如何写入输出。如果您阅读的文件没有jpeg标题,则会中断。