该程序接受文件名作为输入,并应恢复该文件上的所有jpeg。它一次读取512个字节,并检查新jpeg的开头。
程序在运行时会编译,但是会出现分段错误。请告诉我如何解决此问题。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
// check for proper usage
if (argc != 2)
{
printf("Usage: 1 command line argument\n");
return 1;
}
// check if file can be opened
FILE *file = fopen(argv[1], "r");
if (file == NULL)
{
printf("Cannot be opened\n");
return 2;
}
// read 512 bytes into buffer until end of card
int buffer[128];
int counter;
counter = 0;
char filename[8];
FILE *img = NULL;
while(fread(buffer, 4, 128, file) == 128)
{
//check if start of new JPEG
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
//check if first JPEG
if (counter == 0)
{
sprintf(filename, "%03i.jpg", counter);
img = fopen(filename, "w");
fwrite(buffer, 4, 128, img);
counter += 1;
}
else if (counter > 0)
{
fclose(img);
sprintf(filename, "%03i.jpg", counter);
img = fopen(filename, "w");
fwrite(buffer, 4, 128, img);
counter += 1;
}
}
else if (counter > 0)
{
fwrite(buffer, 4, 128, img);
}
}
fclose(img);
fclose(file);
return 0;
}
答案 0 :(得分:0)
fclose(img)
是元凶。 img
为NULL。为了找出原因,您可以在printf
之后插入fopen
。这是link,用于将来调试所有段错误。
$ ./recover card.raw
Memory access error: invalid parameter; abort execution.
# fclose's parameter (0x0) is not a valid FILE pointer.
# Stack trace (most recent call first) of the error.
# [0] file:/recover.c::55, 5
# [1] [libc-start-main]
答案 1 :(得分:0)
调用fread(buffer, 4, 128, file)
将512个字节读取(如您正确地说)到128个整数数组中。但是,当您随后使用以下代码测试新JPEG文件的开头时:
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
//...
您正在检查数组中前四个整数中的每一个的低字节,而不是(应该检查)检查数组中的前四个字节 。这四个字节全部位于第一个整数元素(buffer[0]
)中。
因此,您的程序将永远找不到新的JPEG的开始,因此,img
文件将永远不会打开...然后您用{{1}来调用fclose
}文件指针,这是未定义的行为,很可能导致您看到的分段错误。
代替(假设正确的'endianness'),请执行以下检查:
NULL
要考虑“错误的字节序”,您可以检查if ((buffer[0] & 0xfffffff0) == 0xffd8ffe0)
{
//...
中的任一字节顺序:
buffer[0]
更好的是,只需读取(写入)缓冲区的内容-512字节的数组,并使用如下代码:
if ((buffer[0] & 0xfffffff0) == 0xffd8ffe0 || (buffer[0] & 0xf0ffffff) == 0xe0ffd8ff)
{
//...
这样,您可以保持“ JPEG开始”测试不变。