fclose () verursacht Zugriffsfehler
-
22-07-2019 - |
Frage
Ich habe eine durch Tabulatoren getrennte Textdatei, die ich Parsen bin. Seine erste Spalte enthält Saiten des Formats chrX
, wo X
eine Menge von Zeichenketten bezeichnet, beispielsweise „1“, „2“, ..., „X“, „Y“.
Diese sind jeweils in einem char*
gespeichert genannt chromosome
, da die Datei analysiert wird.
Die Textdatei auf der ersten Spalte sortiert ist lexikographisch, das heißt, muß ich eine Anzahl von Zeilen mit „chr1“ ab, und dann „ChR2“, etc.
Bei jedem „CHRX“ -Eintrag, ich brauche eine andere Datei zu öffnen, die mit diesem Eintrag verknüpft ist:
FILE *merbaseIn;
// loop through rows...
if (chromosome == NULL)
openSourceFile(&chromosome, fieldArray[i], &merbaseIn, GENPATHIN);
else {
if (strcmp(chromosome, fieldArray[i]) != 0) { // new chromosome
fclose(merbaseIn); // close old chromosome FILE ptr
free(chromosome); // free old chromosome ptr
openSourceFile(&chromosome, fieldArray[i], &merbaseIn, GENPATHIN); // set up new chromosome FILE ptr
}
}
// parse row
Ich habe die Funktion openSourceFile
, die wie folgt definiert ist:
void openSourceFile (char** chrome, const char* field, FILE** filePtr, const char *path) {
char filename[100];
*chrome = (char *) malloc ((size_t) strlen(field));
if (*chrome == NULL) {
fprintf(stderr, "ERROR: Cannot allocate memory for chromosome name!");
exit(EXIT_FAILURE);
}
strcpy(*chrome, field);
sprintf(filename,"%s%s.fa", path, field);
*filePtr = fopen(filename, "r");
if (*filePtr == NULL) {
fprintf(stderr, "ERROR: Could not open fasta source file %s\n", filename);
exit(EXIT_FAILURE);
}
}
Das Problem ist, dass meine Anwendung beendet mit einem Segmentierungsfehler aus dem ersten Chromosom in dem zweiten geht (von chr1
zu chr2
) auf der folgende Zeile, wo ich die erste Chromosom Datei zu schließen, die ich geöffnet:
fclose(merbaseIn);
Ich weiß, ich bin fclose
einen NULL-Zeiger nicht vorbei, weil bis zur Segmentation Fault, ich Daten aus dieser Datei lese. Ich kann dies sogar wickeln in einem bedingten und ich bekomme immer noch den Fehler:
if (merbaseIn != NULL) {
fclose(merbaseIn);
}
Außerdem weiß ich openSourceFile
Werke (zumindest für chr1
, wenn die erste Datei-Handle von FILE*
Einrichtung), weil meine Anwendung chr1
Reihen analysiert und liest Daten aus der FILE*
Quelldatei korrekt.
Was es über diesen fclose
Aufruf ist, dass ein Segmentierungsfehler verursacht auftreten?
Lösung
valgrind --db-attach=yes --leak-check=yes --tool=memcheck --num-callers=16 --leak-resolution=high ./yourprogram args
Es ist sehr wahrscheinlich, dass die segfault durch Speicherbeschädigung auf dem Heap verursacht, nicht alles, was die Einheimischen ist zu beeinflussen. Valgrind zeigt Ihnen sofort die ersten falschen Zugriff Sie machen.
Edit: Die --db-attach
Option valgrind
seit Release 3.10.0 im Jahr 2014 weiterentwickelt wurde in der Release Notes Zustand:
The built-in GDB server capabilities are superior and should be used
instead. Learn more here:
http://valgrind.org /docs/manual/manual-core-adv.html#manual-core-adv.gdbserver
Andere Tipps
ein Fehler, den ich feststellen, ist diese Zeile:
*chrome = (char *) malloc ((size_t) strlen(field));
was sein soll:
*chrome = (char *) malloc ((size_t) strlen(field)+1);
Das ist, weil eine Zeichenfolge, die eine Schließung 0 am Ende hat, die Sie auch für Platz zu machen haben
beste Vermutung ist, dass ein anderer Teil des Codes ist verderblicher Speicher durch einen Pufferüberlauf oder Ähnliche Fehler.
Obwohl es unwahrscheinlich ist, die Ursache zu sein, haben Sie eine mögliche Überlaufbedingung in Ihrem Dateinamen Array, wenn der vollständige Dateiname 100 Zeichen überschreitet.
Ich würde vorschlagen, einen Debugger für Änderungen in der Speicherstelle durch die merbaseIn Variable zu beobachten.
Allg Pointer Problem
C ist eine großartige Sprache, aber es erfordert, dass Sie Ihre eigenen Speicher verprügeln. Neben dem Problem zuvor erwähnt, wo der malloc 1 Byte kurz ist, können Sie andere Zeiger Probleme haben.
Ich würde vorschlagen, einen Speicher-Debugger verwenden. In der Vergangenheit Electric Fence war ziemlich beliebt, aber in diesen Tagen I mehr über valgrind hören. Es gibt viele andere Möglichkeiten.
Zusätzlich finden Fehler von reinier , ich vermute, dass:
free(chromosome);
sollte folgen:
chromosome = NULL;
, um eine mögliche Verwendung eines nicht mehr gültigen Wert zu verhindern.
, warum diese FILE ** filePtr wenn nur diese FILE * filePtr würde ausreichen? nur so ein Gedanke ...
valgrind
mit memcheck
ist auf jeden Fall das richtige Werkzeug, die Ursache des Segmentierungsfehler zu entdecken. Um einen Debugger mit valgrind
zu verwenden, beachten Sie, dass die --db-attach
Option valgrind
veraltet ist seit Valgrind 3.10.0 im Jahr 2014 veröffentlicht wurde in der Release Notes Zustand:
The built-in GDB server capabilities are superior and should be used
instead. Learn more here:
http://valgrind.org /docs/manual/manual-core-adv.html#manual-core-adv.gdbserver
Überprüfen Sie jeden Ort, den Sie verwendet "malloc" und sehen Sie, wenn Sie einen Fehler gemacht haben.
Zum Beispiel habe ich anzog aus einer Datei in eine char Leseleitungen **, aber ich falsch malloced es als:
my_list = malloc(sizeof(char) * num_lines_found_in_file);
Wenn es hätte sein sollen:
my_list = malloc(sizeof(char*)* num_lines_found_in_file);