0

I am stuck in this problem, when I run it I keep getting a segmentation fault. I think that the bug in my code is in the while loop. In the walkthrough of the problem it was suggested to check if fread() returned a lower value than 512 to see wether we were or not at the end of the file. I tried to do so but I think the while may not be executed correctly. I would really appreciate it if someone could guide me on how to solve my bug, thank you in advance.

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

typedef uint8_t BYTE;

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

    //Open the file
    FILE *f = fopen(argv[1], "r");
    if (f == NULL)
    {
        printf("Error opening file");
        return 2;
    }

    BYTE buffer[512];
    char image[7];
    int counter = 0;
    FILE *pimage = NULL;

    while (fread(&buffer, 1, 512, f) == 512)
    {
        fread(&buffer, 1, 512, f);
        //Check if it is the start of a jpg file
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            //Check if it is the first jpg
            if (counter == 0)
            {
                sprintf(image, "%03i.jpg", counter);
                counter++;
                pimage = fopen(image, "w");
                fwrite(&buffer, 1, 512, pimage);
            }
            else
            {
                fclose(pimage);
                sprintf(image, "%03i.jpg", counter);
                counter++;
                pimage = fopen(image, "w");
                fwrite(&buffer, 1, 512, pimage);
            }
        }
        else
        {
            fwrite(&buffer, 1, 512, pimage);
        }
    }

    fclose(pimage);
}

0

Impressive! This code has 3 of the most common issues with this pset! First, there's this: char image[7]; The file name contains 7 chars. But, there also needs to be room for the end of string marker, \0. So, it needs to be at least 8 chars.

Second, there are two consecutive fread statements. That means that half the data will be thrown away without being processed. The common misconception is that if a call to fread or similar functions is in a conditional test like a while or if statement, that it's only generating a test result to be checked. In fact, it is most definitely executing the read to generate the return value that will be tested.

Third is the final fwrite statement. This statement will be executed whenever the data block does NOT have a signature. Now, what happens when the first block(s) of data are processed before the first signature block is found? Remember, the output file has not been opened yet, but this fwrite will try to write to a null file pointer. Instant seg fault.

As a review, you should also read the following on how to identify the specific line of code that generates a seg fault. This is a critical skill and is actually seems to be the most common problem for new programmers in this class, beyond the three I already mentioned.

Do YOU know how to find a seg fault?? Advice to new programmers

Happy programming!

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

  • hey, can i ask, why do you have to initialise the filename? – jakec1234 Jul 12 '20 at 12:40
  • Not precisely sure what you mean by "the filename" in this context, but I'll try to cover the bases. A string, char array, of FILE * are all pointers. The rule about pointers is that when they are created, the value in the pointer is NOT initialized. Pointers will contain whatever garbage data exists in the physical memory assigned to that variable. So, best practice is to ALWAYS initialize a pointer variable when it is created. That could mean setting it to NULL, allocating memory with a call to malloc or calloc, or inserting a valid address into that pointer, (continues....) – Cliff B Jul 12 '20 at 21:07
  • (...continued) Or, if it is immediately going to get a valid address assigned to it, only then is it acceptable to not initialize. (It's still a best practice to do so anyways.) You should get in the habit of always initializing variables when created. If you're referring to something else, can you be more specific? – Cliff B Jul 12 '20 at 21:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .