CS50 PSET3 Восстановление ошибки сегментации, невозможно получить код для вывода JPEG - PullRequest
0 голосов
/ 16 апреля 2019

Предполагается, что программа восстанавливает JPEG из необработанного файла, я проверил подобные проблемы, но, похоже, не могу выяснить проблему в моем коде, которая вызывает ошибку сегментации и невозможность вывода изображений. Отладчик в cs50 не работает.

Код:

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

typedef uint8_t  BYTE;

bool checkheader(BYTE buffer[512]);

int main(int argc, char *argv[])
{
    // ensure proper usage
    if (argc != 2)
    {
        printf("Usage: ./recover image\n");
        return 1;
    }

    // save arguments
    char *infile = argv[1];

    // open input file
    FILE *inptr = fopen(infile, "r");
    if(inptr == NULL)
    {
        printf("File could not be read\n");
        return 2;
    }

    //open output file
    FILE* img = NULL;


    BYTE buffer[512];
    int block = 512;
    bool newJpeg = false;
    bool run = false;
    char filename[8];
    int filenameCnt = 0;


    // run until end of file
    while (fread(buffer, 512, 1, inptr) == 1)
    {

        // read 512 blocks UNTIL FIRST HEADER FOUND, checking to see if first four bytes indicate JPEG
        if (newJpeg == false)
        {
            for (int i = 0; i < block; i++)
            {
                fread(&buffer[i], 1, 512, inptr);
            }
        }

        // create jpeg file if jpeg header is found
        if(checkheader(buffer) == true)
        {
            sprintf(filename,"%03d.jpg", filenameCnt); // creating a new jpeg
            filenameCnt++;
            img = fopen(filename, "w"); // making the jpeg writable
            run = true;

            // write data of block after header
            for (int j = 0; j < block - 4; j++)
            {
                fwrite(&buffer[j+4], 1, 512, img);
            }
        }

        // read and write new blocks into jpeg until new header is found
        while (run == true)
        {

            // read new block
            for (int i = 0; i < block; i++)
            {
                fread(&buffer[i], 1, 512, inptr);
            }

            // check if new block has header
            if(checkheader(buffer) == true)
            {
                fclose(img); // close current jpeg so new one could be opened
                newJpeg = true;
                run = false;
            }
            else
                // if not, continue writing new blocks into the current jpeg.
                for (int j = 0; j < block; j++)
                {
                    fwrite(&buffer[j], 1, 512, img);
                }

        }
    }

return 0;

}

bool checkheader(BYTE buffer[512])
{
    if(buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        return true;
    else
        return false;
}

Предполагается вывести 50 файлов JPEG. Любая помощь или наблюдения будут очень благодарны. Спасибо.

1 Ответ

0 голосов
/ 17 апреля 2019

Означает ли это "Отладчик в CS50 не работает" означает debug50?Возможно, вы установили точку останова после сегфоута.Сегфоут приходит сюда fread(&buffer[i], 1, 512, inptr); (строка 51).В принципе, он не может «уместить» 512 байт данных по адресу буфера [i] для некоторого i.

Вообще говоря, входной файл должен читаться в точно одном месте, как здесь: while (fread(buffer, 512, 1, inptr) == 1)

Что будет делать этот цикл:

        for (int i = 0; i < block; i++)
        {
            fread(&buffer[i], 1, 512, inptr);
        }

(если он не был segfault!)?Он собирается прочитать 512 512-байтовых блоков из infile.Ничего себе, он, безусловно, пропустит некоторые действительно важные данные, не так ли?

Программа должна прочитать inptr в одном месте, while подходит, а затем решить, что делать с каждым прочитанным блоком,Существует три варианта:

  • сброс (не найдено первой подписи jpeg)
  • запись в текущий jpeg
  • начало нового jpeg (это блок подписи))

И помните, блок подписи является неотъемлемой и необходимой частью вывода.

// write data of block after header
            for (int j = 0; j < block - 4; j++)
            {
                fwrite(&buffer[j+4], 1, 512, img);
            } 

- это отбрасывание заголовка, что приведет киспорченный вывод.

...