The program is supposed recover JPEG's from a raw file, I've checked similar problems, but can't seem to figure out the problem in my code that's causing the segmentation fault and failure to output images. The debugger in cs50 doesn't function.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
typedef uint8_t BYTE;
bool checkheader(BYTE buffer[512]);
int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
// save arguments
char *infile = argv[1];
// open input file
FILE *inptr = fopen(infile, "r");
if(inptr == NULL)
{
printf("File could not be read\n");
return 2;
}
//open output file
FILE* img = NULL;
BYTE buffer[512];
int block = 512;
bool newJpeg = false;
bool run = false;
char filename[8];
int filenameCnt = 0;
// run until end of file
while (fread(buffer, 512, 1, inptr) == 1)
{
// read 512 blocks UNTIL FIRST HEADER FOUND, checking to see if first four bytes indicate JPEG
if (newJpeg == false)
{
for (int i = 0; i < block; i++)
{
fread(&buffer[i], 1, 512, inptr);
}
}
// create jpeg file if jpeg header is found
if(checkheader(buffer) == true)
{
sprintf(filename,"%03d.jpg", filenameCnt); // creating a new jpeg
filenameCnt++;
img = fopen(filename, "w"); // making the jpeg writable
run = true;
// write data of block after header
for (int j = 0; j < block - 4; j++)
{
fwrite(&buffer[j+4], 1, 512, img);
}
}
// read and write new blocks into jpeg until new header is found
while (run == true)
{
// read new block
for (int i = 0; i < block; i++)
{
fread(&buffer[i], 1, 512, inptr);
}
// check if new block has header
if(checkheader(buffer) == true)
{
fclose(img); // close current jpeg so new one could be opened
newJpeg = true;
run = false;
}
else
// if not, continue writing new blocks into the current jpeg.
for (int j = 0; j < block; j++)
{
fwrite(&buffer[j], 1, 512, img);
}
}
}
return 0;
}
bool checkheader(BYTE buffer[512])
{
if(buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
return true;
else
return false;
}
It's supposed to output 50 JPEG files. Any help or observations would be really appreciated. Thanks.
Does this "The debugger in cs50 doesn't function" mean debug50
? Maybe you have set a breakpoint after the segfault. The segfault comes here fread(&buffer[i], 1, 512, inptr);
(line 51). Basically, it cannot "fit" 512 bytes of data at the address of buffer[i] for some i.
Generally speaking the input file should be read in exactly one place, like here: while (fread(buffer, 512, 1, inptr) == 1)
What is this loop:
for (int i = 0; i < block; i++)
{
fread(&buffer[i], 1, 512, inptr);
}
going to do (if it didn't segfault!)? It is going to read 512 512-byte blocks from the infile. Wow, it will certainly miss some really important data, won't it?
The program needs to read inptr
in one place, the while
is appropriate, then decide what to do with each block read. There are three choices:
And remember, the signature block is an integral and necessary part of the output.
// write data of block after header
for (int j = 0; j < block - 4; j++)
{
fwrite(&buffer[j+4], 1, 512, img);
}
is discarding the header, which will result in corrupt output.