0

When I run my code in debug mode it works fine and creates 50 jpg images. When I run it like ./recover card.raw it waits forever without an error code. When I submit it, it times out. What am I doing wrong?

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

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

    // define variables
    typedef uint8_t BYTE;
    BYTE buffer[512];
    int readBytes = 0;
    int blockNum = 0;
    int numOfImages = 0;

    // open card and open a new file for saving jpeg
    FILE *f = fopen(argv[1], "r");
    FILE *pNewImage;

    // loot through the file and repeat this until the end of a file is reached
    do {
        blockNum++;
        readBytes = fread(buffer, sizeof(BYTE), 512, f);

        // if a block is a start of a new JPEG
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && ((buffer[3] & 0xf0) == 0xe0)) {
            numOfImages++;
            char filename[8];

            if (numOfImages == 1) { // Save buffer to a new file if it's a first image
                sprintf(filename, "%03i.jpg", numOfImages - 1); // write to variable filename like 001.jpg
                pNewImage = fopen(filename, "w");
                fwrite(buffer, sizeof(BYTE), 512, pNewImage);
            } else { // close image file if it's open from last save and save it to a new file
                if (pNewImage != NULL) {
                    fclose(pNewImage);
                }
                sprintf(filename, "%03i.jpg", numOfImages - 1);
                pNewImage = fopen(filename, "w"); // Open a file
                fwrite(buffer, sizeof(BYTE), 512, pNewImage);
            }

            printf("Found beginning of an image in a block %i\n", blockNum);
        } else { // if a block is not a start of a new image
            if (pNewImage != NULL) { // If it's open write, else ignore
                fwrite(buffer, sizeof(BYTE), 512, pNewImage);
            } else {
                continue;
            }
        }
    } while (readBytes == 512);

    fclose(pNewImage);
    fclose(f);

    return 0;
}

In debugger, it creates 50 jpg images and returns fine as you can see in the picture.

CS50 debugger

1

Sometimes, software bugs don't behave the same way inside of a debugger as they do when run normally. You've just discovered one of those cases. When this happens, you should treat it like a seg fault and try to identify the offending line of code. In this case, processing is either being suspended or going into some kind of infinite loop with these two lines:

        if (pNewImage != NULL) { // If it's open write, else ignore
            fwrite(buffer, sizeof(BYTE), 512, pNewImage);

The problem here is that pNewImage was never initialized to NULL. Remember, when a pointer is created, it is not automatically initialized. It will contain random garbage data - whatever was left in that physical memory location the last time it was used. So, results are totally unpredictable. It could contain the equivalent of NULL (if you're unlucky), or a valid address that it shouldn't (if you're really unlucky) or an invalid address that will throw an error (if you're lucky.)

Clean that error up and this immediate problem will be solved.

There are more issues waiting for you, but it wouldn't be right to deprive you of the fun of solving them!

However, there's this hint: How much space needs to be allocated to store the output file names, including the end of string marker?

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

  • I will try your advice for initializing a pointer to null. Before reading your answer I saw that I need a space for null character and I thought this might be it :) – Hrvoje T Jul 21 '20 at 7:52
  • So I had 3 errors. The main one was with the pointer had to be initialized to NULL FILE *pNewImage = NULL like Cliff said. The 2nd was that a filename didn't have a null character. It needs 7 spaces for 000.jpg and one for null character char filename[8]. The 3rd was with do while loop. The last image wasn't the same, so I replaced it with while loop while ((fread(buffer, 512, 1, f)) == 1) while also changing fwrite to fwrite(buffer, 512, 1, pNewImage). Big thanks Cliff, your explanations are great! PS: I didn't know that debugger and normal run can be different. – Hrvoje T Jul 21 '20 at 8:25
  • they can absolutely be different. In fact, sometimes running a program under the debugger will actually mask an error and make things seem correct. That's when you have to resort to manual detective work! ;-) – Cliff B Jul 21 '20 at 8:44

You must log in to answer this question.

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