2017-07-27 10 views
-1

EDIT 2:私の最初の問題につき、それが私たちは、ポインタのファンダメンタルズの赤裸々誤解を見つけCS50 pset4セグメンテーションエラーrecover.c >>何が間違っていますか?

Weather Vane

の助けを経て解決しました。いったん私はポインタ情報を見直し、私は私のセグメンテーションエラーを解決しました。みんなありがとう

OP:

**目標は、JPEGの署名を使用して、すべてのJPEGファイルを回復するために、card.rawファイル与えられた、あるとJPEGが発見されると、他のすべてのJPEGファイルが連続して最後まで続くと仮定ファイルのファイルはFAT 512バイトブロックでフォーマットされます。 **

タイトルのとおり、私はセグメント化エラーを得るために何をしているのか分かりません。私はvalgrindとgcdを使ってデバッグしようとしましたが、私のようにコーディングするのが新しいので、セグメンテーションエラーの原因を見つけることができませんでした。私は、これらのデバッグ機能の出力を解読しようとすると、私が予想していたよりも謎めいていることがわかります。

さらに、私は類似のセグメンテーションエラーで他のものを探しましたが、私が見つけたもの、特にこのサイトで見つけたものは、私が思っていないコードの別のエラーによるものです。

私はバッファが正しく作成されているように見えますが、ファイルは常に条件文でトラップされないように開いたり閉じたりするようにしています。正しいブロックをjpegサイズ。

私はすべての助けを借りていただきありがとうございます。

編集:ここでは、要求されたコメント欄を1として

は私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 

は私のコードです:write_jpeg機能で

#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(file、-4、SEEK_CUR);'の目的を理解できません。あなたは4つの署名バイトをチェックしましたが、実際には512バイトを読んでいました。ほとんどの作業を行っている関数で 'fread'の戻り値をチェックしていないので、これは、1つのjpegのデータを読み取っているループのファイルの終わりを検出しないことを意味します。 –

+0

私はfseekの使用方法を見直しましたが、今はそれが目的ではないと考えています。私は元来、私はinfileのカーソルを4バイト移動して戻ってきたと信じていたので、私はそれを使用しましたが、私はfreadとバッファが提供していた実際のメカニズムについて誤解を持っていました。私が正しく理解していれば、私はfseekを使う必要はありません。 – cartwmic

答えて

0

これは正しくありません。

fread(&buffer, 

fread関数は、書き込む領域へのポインタを要求します。しかし、あなたは、上記のスペースへのポインタが格納されているスペースへのポインタを提供しました。

fread(buffer,である必要があります。 fwriteと同じ間違いをして、mainでも同じ間違いを犯します(ただし、その場合は、実装の詳細により遠ざかります)。

また、count1000に達すると、バッファオーバーフローが発生します。 %03iのprintf指定子は、3の数字であり、最大ではありません。

関連する問題