Sraffa Sraffa - 3 months ago 21
C Question

fopen changes variable value in C

I'm taking the EDx CS50 class from Harvard to learn C and I noticed a strange behavior of my code in one of the problem sets (I already came up with a solution that worked, but I want to understand why the original one doesn't). The idea of the assignment is to check a file where references to jpeg files have been deleted, and thus recover photos from memory.

The issue I have is with the

foundJPEG
boolean below. My original idea was to set it to false until the first photo was found and after that start writing the individual files (they were supposed to be in continuous blocks of memory). The first time a jpeg header was found, a new write file would be generated and the information copied there until a new jpeg was found. Additionally, the
foundJPEG
variable would become
true
. Originally I only had this declaration under the else clause of the
if(foundJPEG)
block of code, but after running it I noticed that every time the
fopen
function was called, the variable went back to
false
. Hence, I just added a new
foundJPEG = true;
statement after opening a new file, even in the case when the variable was already changed to true.

What I want to know is why the boolean is becoming false every time
fopen
is called. In particular, since C gives so much control about memory allocation, I was wondering if it was because it was somehow being overwritten whenever I open a file or because of some scope issue. I guess this is probably a rookie mistake but I thought maybe someone could help me understand this better so that I don't compound mistakes when writing larger applications. Thank you very much!

recover.c
*
* Computer Science 50
* Problem Set 4
*
* Recovers JPEGs from a forensic image.
*/

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

typedef uint8_t BYTE;


int main(int argc, char* argv[])
{
int k = 0;
bool foundJPEG = false;
char title[7];
FILE* file = fopen("card.raw", "rb");
FILE* img;

BYTE buf[512];
int size = sizeof(buf);
while(fread(&buf, size, 1, file) == 1){

if(buf[0] == 0xff && buf[1] == 0xd8 && buf[2] == 0xff && buf[3] >= 0xe0 && buf[3] <= 0xef){

if(foundJPEG){
fclose(img);
k++;
sprintf(title, "%03d.jpg", k);
img = fopen(title, "wb");
foundJPEG = true;
}
else{
sprintf(title, "%03d.jpg", k);
img = fopen(title, "wb");
foundJPEG = true;
}


}
if(foundJPEG){
fwrite(&buf, size, 1, img);
}

}
fclose(img);
return 0;


}

Answer

There are at least two instances of indefined behavour in your code.

fclose(img);

You are calling this with img uninitialized

char title[7];          
sprintf(title, "%03d.jpg", k);

The sprintf will write 8 characters 3+4 + null terminator to a 7 byte buffer which will overwrite something else on your stack.

It's likely one of these causes your issue.

Comments