CS50 pset4分割错误recover.c >>我做错了什么?

问题描述:

编辑2:按我最初的问题,它是通过的CS50 pset4分割错误recover.c >>我做错了什么?

Weather Vane

帮助我们在那里发现指针基本面形成了鲜明的误解得到解决。一旦我查看指针信息,我解决了我的分段错误。谢谢大家

OP:

**,给定一个card.raw文件,使用JPEG签名和假设,一旦JPEG发现恢复所有JPEG文件的目标,所有其他的JPEG文件顺序跟随,直到结束的文件。该文件格式化为FAT 512字节块。 **

正如标题所说,我不知道我在做什么来得到分割错误。我尝试过使用valgrind和gcd进行调试,但是对于编码和我一样新,我无法找到分段错误的来源。我承认,试图破译这些调试功能的输出证明比我所期望的更加神秘。

此外,我搜索了其他人的一个类似的分割错误,但我发现的其他人,特别是在这个网站上,从我没有(我认为)的代码中的另一个错误中找出错误。

这让我疯狂,因为它看起来我已经正确地创建了一个缓冲区,确保文件总是在条件语句中不会捕获它们的情况下打开和关闭,并正确利用fwrite创建一个正确的块的jpeg尺寸。

我感谢所有和任何帮助。

编辑:

按要求进行评议,这是我的valgrind输出:

~/workspace/pset4/recover/ $ valgrind --leak-check=full ./recover card.raw 
==26277== Memcheck, a memory error detector 
==26277== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==26277== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info 
==26277== Command: ./recover card.raw 
==26277== 
==26277== Invalid read of size 1 
==26277== at 0x42DC1F: write_jpeg (recover.c:79) 
==26277== by 0x9A904008211C1099: ??? 
==26277== by 0x82104489A502E0F: ??? 
==26277== by 0x2104082104082103: ??? 
==26277== by 0x408210408210407: ??? 
==26277== by 0x821040821040820: ??? 
==26277== by 0x9304082104082103: ??? 
==26277== by 0x21840021840048: ??? 
==26277== by 0x4208104248208481: ??? 
==26277== by 0x13F0E30705210447: ??? 
==26277== by 0x13E8E0CA918D0902: ??? 
==26277== by 0xD384118482262983: ??? 
==26277== Address 0x821040821040821 is not stack'd, malloc'd or (recently) free'd 
==26277== 
==26277== 
==26277== Process terminating with default action of signal 11 (SIGSEGV) 
==26277== General Protection Fault 
==26277== at 0x42DC1F: write_jpeg (recover.c:79) 
==26277== by 0x9A904008211C1099: ??? 
==26277== by 0x82104489A502E0F: ??? 
==26277== by 0x2104082104082103: ??? 
==26277== by 0x408210408210407: ??? 
==26277== by 0x821040821040820: ??? 
==26277== by 0x9304082104082103: ??? 
==26277== by 0x21840021840048: ??? 
==26277== by 0x4208104248208481: ??? 
==26277== by 0x13F0E30705210447: ??? 
==26277== by 0x13E8E0CA918D0902: ??? 
==26277== by 0xD384118482262983: ??? 
==26277== 
==26277== HEAP SUMMARY: 
==26277==  in use at exit: 1,136 bytes in 2 blocks 
==26277== total heap usage: 2 allocs, 0 frees, 1,136 bytes allocated 
==26277== 
==26277== LEAK SUMMARY: 
==26277== definitely lost: 0 bytes in 0 blocks 
==26277== indirectly lost: 0 bytes in 0 blocks 
==26277==  possibly lost: 0 bytes in 0 blocks 
==26277== still reachable: 1,136 bytes in 2 blocks 
==26277==   suppressed: 0 bytes in 0 blocks 
==26277== Reachable blocks (those to which a pointer was found) are not shown. 
==26277== To see them, rerun with: --leak-check=full --show-leak-kinds=all 
==26277== 
==26277== For counts of detected and suppressed errors, rerun with: -v 
==26277== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 
Segmentation fault 

这里是我的代码:

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 
#include <string.h> 
#include <stdint.h> 



// prototypes 
void write_jpeg(int count, FILE *file, uint8_t buffer[]); 

int main(int argc, char *argv[]) { 
    // ensure correct argument usage 
    if (argc != 2) { 
     fprintf(stderr, "Error. Correct usage: ./recover [infile]\n"); 
     return 1; 
    } 

    // open infile 
    FILE *file = fopen(argv[1], "r"); 

    // ensure can open file 
    if (file == NULL) { 
     fprintf(stderr, "Error, could not open file\n"); 
     return 2; 
    } 

    // initializes bool variable that signals start of jpegs 
    bool start = false; 

    // buffer for file block 
    uint8_t buffer[512]; 

    // loop to find the start of the series of jpegs 
    while (!start) { 
     // read FAT blocks into buffer 
     fread(&buffer, 1, 512, file); 

     if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff 
     && (buffer[3] & 0xf0) == 0xe0) { 
      start = true; 
      fseek(file, -4, SEEK_CUR); 
      memset(buffer, 0x00, 512); 
     } 
    } 

    // count for number of jpegs 
    int count = 0; 

    // loop to create jpegs 
    while ((fread(&buffer, 1, 512, file)) == sizeof(buffer)) { 
     write_jpeg(count, file, buffer); 
    } 

    fclose(file); 

    return 0; 

} 

// writes into a new file until the start of another jpeg 
void write_jpeg(int count, FILE *file, uint8_t buffer[]) { 
    // creates filenames for jpegs 
    char file_name[8]; 
    sprintf(file_name, "%03i.jpg", count); 

    // opens file to write to 
    FILE *img = fopen(file_name, "w"); 

    if (img == NULL) { 
     fprintf(stderr, "Error: couldnt create jpg file\n"); 
     return; 
    } 

    // bool for end condition 
    bool end = false; 

    while (!end) { 
     // ends if reaches new jpeg signature 
     if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff 
     && (buffer[3] & 0xf0) == 0xe0) { 
      end = true; 
      fseek(file, -4, SEEK_CUR); 
      memset(buffer, 0x00, 512); 
      count++; 
     } else { 

     // read the next block into buffer 
     fread(&buffer, 1, 512, file); 

     // write the buffer into the new file 
     fwrite(&buffer, 1, 512, img); 

     } 
    } 

    fclose(img); 
} 
+0

当您使用Valgrind时,您是否崩溃了? Valgrind报告了什么? –

+0

我不明白'fseek(文件,-4,SEEK_CUR);'的用途。您检查了4个签名字节,但您实际上读取的是512个字节 - 至少我们可以*猜测*您已经这样做了,因为您在执行大部分工作的函数中没有检查来自'fread'的返回值。这意味着您不会检测正在读取一个jpeg数据的循环中的文件末尾。 –

+0

我回顾了我对fseek的使用,现在我认为它没有任何用处。我最初使用它是因为我相信我已经将infile的光标移动了4个字节并需要返回,但我误解了fread和缓冲区正在服务的实际机制。如果我正确理解,我不需要使用fseek。 – cartwmic

write_jpeg功能,这是不正确的:

fread(&buffer, 

fread函数需要一个指向要写入的空间的指针。但是,您提供了一个指向空间的指针,其中存储了指向所述空间的指针。

它应该是fread(buffer,。您与fwrite发生同样的错误,并且您在main中也犯了同样的错误(但是在这种情况下,由于实现细节,您会忽略它)。

另外,如果count达到1000,将会出现缓冲区溢出。 %03i printf说明符意味着最低3数字,而不是最大值。