I'm driving myself crazy trying to figure out what is happening with me code.
I'm currently in CS50's pset4. Recover Challenge.
For those who don't know what is it about: We're given a file called card.raw in which there are some deleted photos. Our task is to implement a program that can do a bit of forensics (idyllically) and recover the lost photos.
Hereby I attach my code:
#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
}
Here's the tricky part:
I've successfully recovered all the problem images. But, if I run the code several times, let's say for example, 5 times, I end up having a Segmentation Fault.
When I run check50, I get the following message (I will attach an image with both the segmentation fault after some successful runs and the check50 veredict). Click here to see the image
I just can't get it. I supose there might be some trouble with memory, but I just don't know what is it.
Thank you very much for your time and your help guys. StackOVerFlow is always such a nice place to seek for guidance.
EDIT
If I run echo $?
once the Segmentation Fault has prompted, I get a value of 139.
Here's the terminal prompt screenshot
EDIT
Just as @Thomas Dickey has pointed out, the program was writing on a file regardless of having an open file yet or not.
I've updated and fixed a bit my code in order to keep it cleaner, and added an if condition in order to fix it.
Here's the solution:
#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;
}
The program only opens the output file if the header looks okay, but writes to the output irregardless. If you read a file that doesn't have a jpeg header, it'll break.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.