CS50 восстановить проблему ошибки сегментации - PullRequest
0 голосов
/ 11 сентября 2018

Цель этой программы - восстановить файлы JPG из файла.

Я работал над этой проблемой около четырех или пяти дней в онлайн-классе CS50, и я просто не могу понять это. Я продолжаю получать ошибки сегментации, и я понятия не имею, почему.

Я попробовал debug50 и обнаружил, что я получаю ошибку, когда программа пытается записать новый файл. Почему это так, я не могу понять.

Я ударился головой о стену на этом, и я полностью стер и переписал его несколько раз. Любая помощь будет принята с благодарностью.

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

Ответы [ 3 ]

0 голосов
/ 11 сентября 2018

Хорошо, я понял, что это был оператор НЕ, который я добавил в последнем операторе if, когда то, что я должен был поставить, было:

    if (counter != 0)
    {
        fwrite(buffer, sizeof(buffer), 1, img);
    }

Однако я все еще не понимаю, почему программа вернула ошибку сегментации.

Насколько я понимаю, когда программа достигла этого конкретного оператора if, она не будет выполнена, поскольку счетчик будет оценен как ложный.

Разве программа не закончила бы после прочтения всего входного файла, возвращая 0?

Откуда происходит ошибка сегментации?

0 голосов
/ 11 сентября 2018

В дополнение к ответу выше ,

Посмотрите на синтаксис функции fwrite:

https://en.cppreference.com/w/c/io/fwrite

size_t fwrite( const void *buffer, size_t size, size_t count,
               FILE *stream );

Согласно документации, параметр size - это размер каждого значения в buffer.

. В вашем коде есть:

fwrite(buffer, 512, 1, img);

Проблема очевидна.

Похоже, вы делаете то же самое для fread.Синтаксис функции:

https://en.cppreference.com/w/c/io/fread

size_t fread( void          *buffer, size_t size, size_t count,
              FILE          *stream );

В вашем коде вы делаете:

fread(buffer, 512, 1, inptr)

Но это должно быть

fread(buffer, sizeof *buffer, 512, inptr)

Кроме того, при работе с такими файлами я рекомендую открывать их в двоичном режиме, чтобы не вмешиваться в считываемые данные.

FILE *inptr = fopen(infile, "rb");

Наконец, вы должны сделатьиспользуйте возвращаемое значение fread, которое сообщает количество фактически прочитанных байтов.Затем вы можете использовать это значение в fwrite, чтобы убедиться, что вы записали правильное количество байтов.

0 голосов
/ 11 сентября 2018
char filename[7];
sprintf(filename, "%03i.jpg", counter);

Строка из семи символов занимает 8 символов из-за NUL-терминатора \0. Увеличьте массив, чтобы не писать после его конца.

if(img == NULL)
{
    fprintf(stderr, "Could not create image file\n");
    fclose(img);
    return 3;
}

Если img не открылся, его не нужно закрывать. С другой стороны, если он открылся, вам нужно закрыть его. Переместите вызов fclose() в конец цикла.

...