-1

大きな .raw ファイルから 50 個の jpeg を 1 つずつコピーしようとしていますが、現在、セグメンテーション違反エラーが発生します。これが私のコードです:

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

typedef uint8_t BYTE;

//SOI - 0xFF 0xD8
//EOI - 0xFF 0xD9
//APPn - 0xFF 0xEn    
int main(void)
{
    //FAT - 512 bytes per block
    BYTE block[512];

    //open file containing pictures
    FILE* card_file = fopen("card.raw", "rd");

    FILE* jpeg_file;

    //make sure the file opened without errors
    if (card_file == NULL)
    {
        printf("something went wrong and file could not be opened");
        return 1;
    }

    int i = 0;
    while (fread(&block, sizeof(BYTE), 512, card_file) != 0)
    {
        //jpeg start signature
        if(block[0] == 0xFF && block[1] == 0xD8)
        {
            i++;
            if(jpeg_file != NULL)
                fclose(jpeg_file);

            //create a new jpeg file to copy bytes to
            jpeg_file = fopen((char*)i, "w+");
        }

        //write 512 bytes to a jpeg file
        if(jpeg_file != NULL)
            fwrite(block, sizeof(block), 1, jpeg_file);
    }

    fclose(card_file);
return 0;
}

GDB を介して実行すると、コードは if(block[0] == 0xFF && block 1 == 0xD8) まで到達し、条件をスキップしてセグメンテーション違反が発生します。何が原因なのかわかりません。スクリーンショットは次のとおりです。 ここに画像の説明を入力

コードが更新されました:

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

typedef uint8_t BYTE;

/*struct jpg*/
/*{*/
/*    BYTE soi[2] = { 0xFF, 0xD8 };*/
/*    BYTE eoi[2] = { 0xFF, 0xD9 };*/
/*};*/

//SOI - 0xFF 0xD8
//EOI - 0xFF 0xD9
//APPn - 0xFF 0xEn    
int main(void)
{
    //FAT - 512 bytes per block
    BYTE block[512];

    //jpeg name
    char name[6];

    bool is_open = false;

    //JPEG
    //struct jpg image;

    //open file containing pictures
    FILE* card_file = fopen("card.raw", "r");

    FILE* jpeg_file;

    //make sure the file opened without errors
    if (card_file == NULL)
    {
        printf("something went wrong and file could not be opened");
        return 1;
    }

    int i = 0;
    while (fread(block, sizeof(BYTE), 512, card_file) != 0)
    {
        //jpeg start signature
        if ((block[0] == 0xFF) && (block[1] == 0xD8) && (block[2] == 0xFF) && ((block[3] == 0xe1) || (block[3] == 0xe0)))
        {
            //assign jpeg name
            sprintf(name, "%d.jpg", i++);
            if(is_open)
                fclose(jpeg_file);

            //create a new jpeg file to copy bytes to
            jpeg_file = fopen(name, "a+");
            is_open = true;
        }

        //write 512 bytes to a jpeg file
        if(is_open)
            fwrite(block, sizeof(block), 1, jpeg_file);
    }

    fclose(jpeg_file);
    fclose(card_file);
return 0;
}

現在はクラッシュしませんが、50 枚の JPEG のうち 9 枚のみが適切に復元されています。cs50.h があるので、ブール型にアクセスできます。50 個のファイルを書き込むより良い方法は何ですか? ブール値に論理的な欠陥があるようです。

4

2 に答える 2

1

fopen((char*)i, "w+");は完全に無効です。整数をポインターとしてキャストしているため、クラッシュします。

番号をファイル名としてフォーマットする必要があります。

char path[PATH_MAX];
sprintf(path, "%d", i);
fopen(path, "w+");

また、初期化していませんjpeg_file-条件が失敗した場合、jpeg_fileワイルドポインターになり、これもクラッシュします。jpeg_fileに初期化する必要がありますNULL

于 2013-03-19T00:28:59.343 に答える
0

fread呼び出しでは、配列のアドレスを渡す必要があります。したがって、ステートメントはfread(block, sizeof(BYTE), 512, card_file).

追記:

  1. あなたのコードでは、入力ファイルのサイズが 512 の整数倍であると仮定していますが、これはJPEGファイルの場合には当てはまりません。最後freadは、実装ロジックで処理する必要がある 512 未満の数値を返す場合があります。したがって、書き込む要素の数は、の戻り値によって決定する必要があります。fread

  2. jpeg_fileループが終了したら、ポインターを閉じる必要があります。

  3. 最後に、JPEGを使用しているため、サムネイル付きのEXIFファイルのケースを処理したい場合があります。この場合、2 つのSOI (画像の開始) マーカーを取得します。

于 2013-03-19T00:29:38.253 に答える