对于我的C类,我必须编写一个程序来查看SD卡,或者真正的card.raw文件,并拉出意外删除的图像。我遇到的问题是我一直遇到分段错误,我不知道为什么。我想可能是我没有正确使用数据指针,但我不知道如何做到这一点。我会在这里有一些代码,所以我很感激!应该看的部分是恢复功能,因为它有麻烦的部分,老师几乎给了我们其余的代码。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
// Function prototypes. Don't change these.
unsigned char * read_card(char * fname, int *size);
void save_jpeg(unsigned char * data, int size, char * fname);
void recover(unsigned char * data, int size);
int main()
{
// Read the card.raw file into an array of bytes (unsigned char)
int card_length;
unsigned char *card = read_card("card.raw", &card_length);
// Recover the images
recover(card, card_length);
}
unsigned char * read_card(char * fname, int * size)
{
struct stat st;
if (stat(fname, &st) == -1)
{
fprintf(stderr, "Can't get info about %s\n", fname);
exit(1);
}
int len = st.st_size;
unsigned char *raw = (unsigned char *)malloc(len * sizeof(unsigned
char));
FILE *fp = fopen(fname, "rb");
if (!fp)
{
fprintf(stderr, "Can't open %s for reading\n", fname);
exit(1);
}
char buf[512];
int r = 0;
while (fread(buf, 1, 512, fp))
{
for (int i = 0; i < 512; i++)
{
raw[r] = buf[i];
r++;
}
}
fclose(fp);
*size = len;
return raw;
}
void save_jpeg(unsigned char * data, int size, char * fname)
{
FILE *fp = fopen(fname, "wb");
if (!fp)
{
fprintf(stderr, "Can't write to %s\n", fname);
exit(1);
}
fwrite(data, 1, size, fp);
fclose(fp);
}
void recover(unsigned char * data, int size){
int start=0;
int length=0;
int count=0;
char name[64];
for( int i = 0; i < size ;i++ ){
if ((data[i] == 0xff && data[i+1] == 0xd8 && data[i+2] == 0xff &&
data[i+3] == 0xe0) ||
(data[i] == 0xff && data[i+1] == 0xd8 && data[i+2] == 0xff &&
rmdata[i+3] == 0xe1)){
start = i;
}
if(data[i] == 0xd9){
length = i - start;
count++;
sprintf(name,"pic%d.jpeg",count);
save_jpeg(data[start], length, name);
}
}
}
答案 0 :(得分:1)
您阅读的方式有点不对,只有在文件大小合适时才会有效
512的倍数。您必须获得读取和写入的字节数fread
只有这个数额。因为您正在读取512字节的块,最后一块
可能不会那么大,因此你可能溢出缓冲区,导致a
段错误。
将您的阅读更改为:
unsigned char buf[512];
size_t n;
while ((n = fread(buf, 1, sizeof buf / sizeof buf[0], fp)))
{
for (int i = 0; i < n; i++) // the i < n is the correct way
{
raw[r] = buf[i];
r++;
}
}
当函数失败时执行exit(1)
也是不好的做法,这样做会更好
此函数应该返回NULL
而调用函数应该检查
如果返回值为NULL
:
unsigned char * read_card(char * fname, int * size)
{
struct stat st;
if (stat(fname, &st) == -1)
{
fprintf(stderr, "Can't get info about %s\n", fname);
return NULL; // <-- here do not do exit
}
...
}
int main(void)
{
int card_length;
unsigned char *card = read_card("card.raw", &card_length);
if(card == NULL)
{
fprintf(stder, "Error, could not read card.raw\n");
return 1;
}
recover(card, card_length);
// do not forget to free the memory
free(card);
return 0;
}
同样do not cast malloc
,请这样做:
unsigned char *raw = malloc(len * sizeof *raw);
因为char
的大小定义为1,所以在这种情况下你甚至可以
删除* sizeof *raw
。
我不知道jpeg格式是如何工作的,所以我无法评论你的格式
recover
正在做正确的事情。但是你应该考虑一件事
约:
for( int i = 0; i < size ;i++ ) {
if ((data[i] == 0xff && data[i+1] == 0xd8 && data[i+2] == 0xff &&
data[i+3] == 0xe0) ...
}
当你到达最后2次迭代(i == size - 2
),data[i+2]
和
data[i+3]
将超出界限,因此您应该在访问之前检查它
data[i+2]
和data[i+3]
。对于最后一次迭代也是如此,
data[i+1]
也将超出范围。就像我说的,我不知道jpeg是如何工作的
所以我不知道所有这些值的含义(例如0xff
或0xd8
)。但是我
认为在你可能需要的save_jpeg(data[start], length, name);
之后
做return
。