2017-07-27 2 views
-1

EDIT 2: Per meinem ersten Problem wurde durch die Hilfe vonCS50 pset4 Segmentierungsfehler recover.c >> Was mache ich falsch?

Weather Vane

Wo wir ein krassen Missverständnis der Zeiger Fundamentaldaten gefunden gelöst. Nachdem ich die Zeigerinformationen überprüft hatte, löste ich meinen Segmentierungsfehler. Vielen Dank alle

OP:

** Das Ziel ist, eine card.raw Datei angegeben, alle JPEG-Dateien mit der JPEG-Signatur zu erholen und unter der Annahme, dass, sobald ein jpeg gefunden, alle andere JPEG-Dateien folgen nacheinander bis zum Ende der Datei. Die Datei ist in FAT 512 Byte Blöcken formatiert. **

Wie der Titel sagt, bin ich nicht sicher, was ich mache, um den Segmentierungsfehler zu bekommen. Ich habe das Debuggen mit valgrind und gcd ausprobiert, aber da ich so neu im Coding bin wie ich bin, konnte ich die Quelle des Segmentierungsfehlers nicht finden. Ich gebe zu, dass der Versuch, die Ausgabe dieser Debugging-Funktionen zu entschlüsseln, kryptischer ist, als ich erwartet hatte.

Darüber hinaus habe ich nach anderen mit einem ähnlichen Segmentierungsfehler gesucht, aber die anderen, die ich vor allem auf dieser Website gefunden habe, Quelle der Fehler von einem anderen Fehler im Code, den ich nicht habe (glaube ich).

Es macht mich wahnsinnig wie es scheint, habe ich einen Puffer richtig erstellt, sichergestellt, dass Dateien immer geöffnet und geschlossen werden im Kontext nicht in bedingten Anweisungen abzufangen, und fwrite korrekt verwendet, um eine JPEG des richtigen Blocks zu erstellen Größe.

Ich schätze alle und jede Hilfe gegeben.

EDIT:

Gemäß einem Kommentator angefordert, hier ist mein valgrind Ausgang:

~/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 

Hier ist mein Code:

#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

Haben Sie bei der Verwendung von Valgrind einen Absturz bekommen? Was hat Valgrind gemeldet? –

+0

Ich verstehe nicht den Zweck von 'fseek (file, -4, SEEK_CUR);'. Sie haben 4 Signatur-Bytes geprüft, aber Sie haben tatsächlich 512 Bytes gelesen - zumindest können wir * raten *, dass Sie das getan haben, da Sie den Rückgabewert von 'fread' in der Funktion, die die meiste Arbeit erledigt, nicht überprüfen. Dies bedeutet, dass Sie das Ende der Datei in der Schleife, die die Daten eines JPEGs liest, nicht erkennen. –

+0

Ich überprüfte meine Verwendung von fseek, und ich glaube jetzt, dass es keinen Zweck erfüllt. Ich habe es ursprünglich benutzt, weil ich glaubte, dass ich den Cursor des Infiles um 4 Bytes verschoben hatte und zurückkommen musste, aber ich hatte ein falsches Verständnis des tatsächlichen Mechanismus, den der Puffer lieferte. Wenn ich richtig verstehe, brauche ich fseek nicht zu benutzen. – cartwmic

Antwort

0

In der write_jpeg Funktion dieser falsch ist:

fread(&buffer, 

Die Funktion fread erwartet einen Zeiger auf das Leerzeichen, in das geschrieben werden soll. Sie haben jedoch einen Zeiger auf den Raum angegeben, in dem ein Zeiger auf den Raum gespeichert ist.

Es sollte fread(buffer, sein. Sie machen den gleichen Fehler mit fwrite, und Sie machen auch den gleichen Fehler in main (aber in diesem Fall kommen Sie damit aufgrund der Implementierungsdetails).

Es kommt auch zu einem Pufferüberlauf, wenn count1000 erreicht. Der %03i printf-Bezeichner bedeutet Minimum von 3 Ziffern, nicht ein Maximum.