CS50 的 pset4 上的分段错误
Segmentation Fault on CS50's pset4
我快把自己逼疯了,想弄清楚我的代码发生了什么。
我目前在 CS50 的 pset4 中。恢复挑战。
对于那些不知道它是关于什么的人:
我们得到了一个名为 card.raw 的文件,其中有一些已删除的照片。我们的任务是实施一个程序,该程序可以(田园诗般地)进行一些取证并恢复丢失的照片。
特此附上我的代码:
#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
}
这是棘手的部分:
我已经成功恢复了所有问题图像。
但是,如果我多次 运行 代码,比方说,5 次,我最终会出现分段错误。
当我 运行 check50 时,我收到以下消息(我将在成功 运行s 和 check50 veredict 后附上包含分割错误的图像)。 Click here to see the image
我就是听不懂。我想可能是内存有问题,但我只是不知道它是什么。
非常感谢您的宝贵时间和您的帮助。 Whosebug 始终是寻求指导的好地方。
编辑
如果我 运行 echo $?
一旦出现分段错误提示,我得到值 139。
Here's the terminal prompt screenshot
编辑
正如@Thomas Dickey 指出的那样,无论是否打开文件,程序都在写入文件。
我已经更新并修复了一些我的代码以使其更清晰,并添加了一个 if 条件以修复它。
解决方法如下:
#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;
}
如果 header 看起来没问题,程序只会打开输出文件,但无论如何都会写入输出。如果您读取一个没有 jpeg header 的文件,它就会损坏。
我快把自己逼疯了,想弄清楚我的代码发生了什么。
我目前在 CS50 的 pset4 中。恢复挑战。
对于那些不知道它是关于什么的人: 我们得到了一个名为 card.raw 的文件,其中有一些已删除的照片。我们的任务是实施一个程序,该程序可以(田园诗般地)进行一些取证并恢复丢失的照片。
特此附上我的代码:
#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
}
这是棘手的部分:
我已经成功恢复了所有问题图像。 但是,如果我多次 运行 代码,比方说,5 次,我最终会出现分段错误。
当我 运行 check50 时,我收到以下消息(我将在成功 运行s 和 check50 veredict 后附上包含分割错误的图像)。 Click here to see the image
我就是听不懂。我想可能是内存有问题,但我只是不知道它是什么。
非常感谢您的宝贵时间和您的帮助。 Whosebug 始终是寻求指导的好地方。
编辑
如果我 运行 echo $?
一旦出现分段错误提示,我得到值 139。
Here's the terminal prompt screenshot
编辑
正如@Thomas Dickey 指出的那样,无论是否打开文件,程序都在写入文件。
我已经更新并修复了一些我的代码以使其更清晰,并添加了一个 if 条件以修复它。
解决方法如下:
#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;
}
如果 header 看起来没问题,程序只会打开输出文件,但无论如何都会写入输出。如果您读取一个没有 jpeg header 的文件,它就会损坏。