CS50恢复分段故障问题
该程序的目标是从文件中恢复JPGs 在CS50在线课程中,我研究这个问题已经有四五天了,我就是想不出来。我继续得到分割错误,我不知道为什么 我尝试了debug50,发现当程序试图写入新文件时,我出现了错误。我不明白为什么会这样 这一次我的头撞到墙上,我已经完全抹掉并重写了好几次。任何帮助都将不胜感激CS50恢复分段故障问题,c,segmentation-fault,cs50,C,Segmentation Fault,Cs50,该程序的目标是从文件中恢复JPGs 在CS50在线课程中,我研究这个问题已经有四五天了,我就是想不出来。我继续得到分割错误,我不知道为什么 我尝试了debug50,发现当程序试图写入新文件时,我出现了错误。我不明白为什么会这样 这一次我的头撞到墙上,我已经完全抹掉并重写了好几次。任何帮助都将不胜感激 #include <stdio.h> #include <stdlib.h> #include <stdint.h> int main(int argc, ch
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage ./recover file.type\n");
return 1;
}
char *infile = argv[1];
FILE *inptr = fopen(infile, "rb");
if (inptr == NULL)
{
fprintf(stderr, "Could not open file designated to be recovered\n");
fclose(inptr);
return 2;
}
int counter = 0;
FILE *img;
uint8_t buffer[512];
while (fread(buffer, sizeof(*buffer), 512, inptr))
{
if (buffer[0] == 0xff &&
buffer[1] == 0xd8 &&
buffer[2] == 0xff &&
(buffer[3] & 0xf0) == 0xe0)
{
if (counter > 0)
{
fclose(img);
}
char filename[8];
sprintf(filename, "%03i.jpg", counter);
img = fopen(filename, "w");
counter++;
}
if (counter !=0)
{
fwrite(buffer, sizeof(*buffer), 512, img);
}
}
fclose(img);
fclose(inptr);
return 0;
}
#包括
#包括
#包括
int main(int argc,char*argv[])
{
如果(argc!=2)
{
fprintf(stderr,“用法./recover file.type\n”);
返回1;
}
char*infle=argv[1];
文件*inptr=fopen(填充“rb”);
如果(inptr==NULL)
{
fprintf(stderr,“无法打开指定要恢复的文件”\n);
fclose(inptr);
返回2;
}
int计数器=0;
文件*img;
uint8_t缓冲器[512];
while(fread(缓冲区,sizeof(*缓冲区),512,inptr))
{
如果(缓冲区[0]==0xff&&
缓冲区[1]==0xd8&&
缓冲区[2]==0xff&&
(缓冲区[3]&0xf0)==0xe0)
{
如果(计数器>0)
{
fclose(img);
}
字符文件名[8];
sprintf(文件名为“%03i.jpg”,计数器);
img=fopen(文件名,“w”);
计数器++;
}
如果(计数器!=0)
{
fwrite(缓冲区,sizeof(*缓冲区),512,img);
}
}
fclose(img);
fclose(inptr);
返回0;
}
由于NUL终止符\0
,七个字符的字符串占用8个字符。使数组变大,这样就不会写过数组的末尾
if(img == NULL)
{
fprintf(stderr, "Could not create image file\n");
fclose(img);
return 3;
}
如果
img
未打开,则无需关闭它。另一方面,如果它确实打开了,那么您确实需要关闭它。将fclose()
调用移动到循环的末尾。好的,所以我发现我在上一个if语句中输入的不是运算符,而我应该输入的是:
if (counter != 0)
{
fwrite(buffer, sizeof(buffer), 1, img);
}
然而,我仍然对程序返回分段错误的原因感到困惑
我的理解是,当程序到达这个特定的if语句时,它将不会执行,因为计数器的计算结果将为false
在读取返回0的整个输入文件后,程序不就结束了吗
分段错误从何而来?除了答案
查看fwrite
函数的语法:
根据文档,size
参数是缓冲区中每个值的大小
在代码中,您有:
fwrite(buffer, 512, 1, img);
问题是显而易见的
看起来您对fread
也这样做。函数的语法为:
在代码中,您可以执行以下操作:
fread(buffer, 512, 1, inptr)
但应该是这样
fread(buffer, sizeof *buffer, 512, inptr)
另外,在处理此类文件时,我建议以二进制模式打开它们,以免篡改正在读取的数据
FILE *inptr = fopen(infile, "rb");
最后,您应该使用fread
的返回值,它告诉您实际读取的字节数。然后,您可以在fwrite
中使用此值来确保写入的字节数正确。我不太理解您对fclose()函数调用的看法。你能澄清一下吗?如果img==NULL
那么你不应该调用fclose(img)
,因为你只是在传递一个NULL
指针。文件未成功打开,因此不要试图关闭它。相反,当您处理完文件时,应该在while
循环的末尾调用fclose(img)
,但该调用丢失了。在循环结束后,您有一个对fclose()
的调用,但它实际上应该在最后的循环中。我已经对代码实现了本线程中提到的更改,但仍然存在分段错误。只有将fclose()调用移到while循环之外,故障才会消失。我完全糊涂了。我做错了什么?好吧,这很有道理。然而,我发现,在更改名称字符串中的字符数并更改我所描述的最后一个if语句后,我能够交换fwrite和fread中的数字,并且程序仍然成功运行。这里还有什么我遗漏的吗?@zachdalton,成功运行并不意味着它是正确的。例如,如果查看fwrite
的文档,您会发现它没有检查数组的大小,它所关心的只是将大小为size
的对象写入缓冲区。在你的例子中,它工作是因为它将大小为512
字节的1
对象写入你的数组,而你的数组正好工作,因为你的数组可以占用512
字节。我明白了。我显然有很多东西要学。我感谢你的帮助。我觉得当我在学习这一切的时候,我错过了很多我应该学习的细微差别和更好的地方。@zachdalton,yw。不用担心,它很快就会成为第二天性。交换大小和计数参数不会破坏任何东西。它们是可互换的。分割错误发生在哪里?使用-g
标志编译程序,然后使用gdb
运行二进制文件。这将告诉您分段错误发生的位置!计数器
和计数器!=0是等效表达式。他们做完全相同的事情。这只是巧合,当你改变那条线时,行为发生了变化。这是我在观看使用操作符的讲座后最初的想法。另一个教程让我很困惑,因为在我换了它之后它就起作用了,所以我认为我错了。
fread(buffer, 512, 1, inptr)
fread(buffer, sizeof *buffer, 512, inptr)
FILE *inptr = fopen(infile, "rb");