CS50 pset4分段错误recover.c>>我究竟做错了什么?

时间:2017-07-27 05:31:00

标签: c segmentation-fault cs50 recover

编辑2:根据我最初的问题,它是通过

的帮助解决的
  

风向标

我们发现了对指针基本面的严重误解。一旦我查看了指针信息,我解决了我的分段错误。谢谢大家

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);
}

1 个答案:

答案 0 :(得分:0)

write_jpeg函数中,这是不正确的:

 fread(&buffer,

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

应该是fread(buffer,。您使用fwrite犯了同样的错误,并且您在main中也犯了同样的错误(但是在这种情况下,由于实现细节,您可以使用它)。

此外,如果count达到1000,则会出现缓冲区溢出。 %03i printf说明符表示3位的最小,而不是最大值。