2016-06-04 15 views
-1

Ich muss eine Datei lesen und dafür verwende ich die Funktion getline. Das Folgende ist ein Beispiel von dieser Webseite: http://crasseux.com/books/ctutorial/getline.html das ich temperiert habe, um eine Datei öffnen zu können.Segmentation Fehler in C get Zeile

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


int main() 
    { 
    int bytes_read; 
    unsigned long nbytes = 100; 
    char *my_string; 
    char *filename; 
    char *line; 
    FILE *fd = NULL; 


    puts ("enter filename"); 

    filename = (char *) malloc (nbytes + 1); 

    bytes_read = getline (&filename, &nbytes, stdin); 

    fd = fopen(filename, "r"); 

    bytes_read = getline (&line, &nbytes, fd); 

    puts (line); 

    puts ("Please enter a line of text."); 

    /* These 2 lines are the heart of the program. */ 
    my_string = (char *) malloc (nbytes + 1); 
    bytes_read = getline (&my_string, &nbytes, stdin); 

    if (bytes_read == -1) 
    { 
     puts ("ERROR!"); 
    } 
    else 
    { 
     puts ("You typed:"); 
     puts (my_string); 
    } 

    return 0; 
} 

und wenn ich das Programm starte, bekomme ich einen Segmentierungsfehler 11, und ich weiß nicht, was ich falsch mache. Vielen Dank im Voraus.

+2

Überprüfen Sie immer, dass Sie die Datei erfolgreich geöffnet haben. Sie haben den Zeilenumbruch nicht von der Zeichenfolge entfernt, die von der get-Zeile zurückgegeben wurde, sodass Sie wahrscheinlich keine Datei mit einem Zeilenumbruch am Ende des Namens geöffnet haben. –

+2

Es ist auch üblich, 'fd' für einen Dateideskriptor (vom Typ' int') und 'fp' für einen Dateizeiger (stream - vom Typ' FILE * ') zu verwenden. –

Antwort

1

Ihre filename lesen von stdin ist falsch für ein Datei-Datei-Argument. Der filename get-Wert von stdin ist beispielsweise 'a.txt \ n', wenn a.txt eingegeben wird.

Also, das Hinzufügen einer Anweisung die Änderung der '\ n' mit '\ 0' wird das Problem lösen. Das ist filename[bytes_read - 1] = '\0'; Anweisung direkt unter der bytes_read = getline (&filename, &nbytes, stdin); Anweisung hinzugefügt.

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


int main() 
    { 
    int bytes_read; 
    unsigned long nbytes = 100; 
    char *my_string; 
    char *filename; 
    char *line; 
    FILE *fd = NULL; 


    puts ("enter filename"); 

    filename = (char *) malloc (nbytes + 1); 

    bytes_read = getline (&filename, &nbytes, stdin); 

    filename[bytes_read - 1] = '\0'; 

    fd = fopen(filename, "r"); 

    bytes_read = getline (&line, &nbytes, fd); 

    puts (line); 

    puts ("Please enter a line of text."); 

    /* These 2 lines are the heart of the program. */ 
    my_string = (char *) malloc (nbytes + 1); 
    bytes_read = getline (&my_string, &nbytes, stdin); 

    if (bytes_read == -1) 
    { 
     puts ("ERROR!"); 
    } 
    else 
    { 
     puts ("You typed:"); 
     puts (my_string); 
    } 

    return 0; 
} 
+1

Also war der "Bug" tatsächlich das Auslassen der Fehlerprüfung. – alk

+1

Diese Lösung schlägt fehl, wenn Sie nur Strg-D drücken, statt einen Namen einzugeben, gefolgt von Enter. – alk

+0

Anyway das 'fgets()' ish '\ n' ist ein schöner Fang, den ich verpasste. :-) – alk

1

Entweder

  • machen line Punkt bis zu einem gewissen gültigen Speicher und nbytes die Größe des Speichers

oder

  • oder line-NULL und nbytes-0 gesetzt.

Von man getline:

ssize_t getline(char **lineptr, size_t *n, FILE *stream); 

getline() liest eine ganze Zeile aus dem Strom, um die Adresse des Puffers speichert den Text in * lineptr enthält. Der Puffer ist nullterminiert und enthält das Newline-Zeichen, falls eines gefunden wurde.

Wenn * lineptr auf NULL gesetzt ist und * n vor dem Aufruf auf 0 gesetzt ist, dann wird getline() einen Puffer zum Speichern der Zeile zuweisen.

Auch getline() erwartet ein size_t als 2. Parameter keine unsigned long.

Auch^2 gibt es keine Notwendigkeit, 1 Byte mehr zu vergeben als an getline übergeben wird. Weisen Sie n Bytes zu und übergeben Sie n, keine Notwendigkeit, n - 1 zu übergeben.


Und immer Fehler in dem entsprechenden Systemaufruf überprüft, wie malloc() und fopen(), bevor das Ergebnis mit ihrer Rückkehr.

+0

Also, was ist falsch bitte? – alk

+0

hi @alk, dies ist nicht die Ursache für den segfault, obwohl Getline-Aufruf-Argument überprüft werden sollte. Diese Antwort ist zu allgemein. – lulyon

+0

Dieser Aufruf würde definitiv UB aufrufen und mit diesem kann alles von diesem zweiten Aufruf von 'getline()' an, einschließlich einer Segmentierungsverletzung. Ich denke auch, dass das überhaupt nicht "allgemein" ist, sondern einen sehr spezifischen Fehler im gezeigten Code zeigt. @lulyon – alk