2012-05-19 1 views
8

Warum kehrt der folgende Code mit einem Segmentierungsfehler zurück? Wenn ich Zeile 7 auskommentiere, verschwindet der Seg-Fehler.Segmentierungsfehler - C

int main(void){ 
     char *s; 
     int ln; 
     puts("Enter String"); 
     // scanf("%s", s); 
     gets(s); 
     ln = strlen(s); // remove this line to end seg fault 
     char *dyn_s = (char*) malloc (strlen(s)+1); //strlen(s) is used here as well but doesn't change outcome 
     dyn_s = s; 
     dyn_s[strlen(s)] = '\0'; 
     puts(dyn_s); 
     return 0; 
    } 

Prost!

+0

@Lundin an einen unbekannten Ort beziehe werden, bitte darauf hinweisen, was das ist ein Duplikat ? Wenn Sie sich auf https://stackoverflow.com/questions/37549594/why-do-i-get-a-mysterious-crash-or-segmentierung-fault-when-i-copy-scan-data-to beziehen , Würde ich sagen, dass meine Frage 4 Jahre älter ist – ceod

Antwort

12

s ist ein nicht initialisierter Zeiger; Sie schreiben an einen zufälligen Speicherort im Speicher. Dies ruft undefiniertes Verhalten auf.

Sie müssen etwas Speicher für s reservieren. Auch never use gets; Es gibt keine Möglichkeit, zu verhindern, dass es den zugewiesenen Speicher überläuft. Verwenden Sie stattdessen fgets.

+0

Vielen Dank Oli! Verzeihen Sie, dass ich ein Schädling bin, aber ich muss verstehen, dass das Hinzufügen der von mir erwähnten Linie dazu führt, dass das undefinierte Verhalten zu einem Seg-Fehler führt. Könntest du mir helfen, die Kausalität ein wenig mehr zu visualisieren? – ceod

+0

@resonant_fractal: Es ist schwer zu sagen. Undefiniertes Verhalten bedeutet definitionsgemäß, dass Ihr Programm alles kann, auch unvorhersehbare Fehler. Ich könnte Vermutungen anstellen, aber die einzige Möglichkeit, dies sicher zu wissen, wäre, sich den Maschinencode anzusehen, den Ihr Compiler erstellt hat. –

+0

Vielen Dank Oli! – ceod

2

katastrophal schlecht:

int main(void){ 
     char *s; 
     int ln; 
     puts("Enter String"); 
     // scanf("%s", s); 
     gets(s); 
     ln = strlen(s); // remove this line to end seg fault 
     char *dyn_s = (char*) malloc (strlen(s)+1); //strlen(s) is used here as well but doesn't change outcome 
     dyn_s = s; 
     dyn_s[strlen(s)] = '\0'; 
     puts(dyn_s); 
     return 0; 
    } 

Besser:

#include <stdio.h> 
#define BUF_SIZE 80 

int 
main(int argc, char *argv[]) 
{ 
     char s[BUF_SIZE]; 
     int ln; 
     puts("Enter String"); 
     // scanf("%s", s); 
     gets(s); 
     ln = strlen(s); // remove this line to end seg fault 
     char *dyn_s = (char*) malloc (strlen(s)+1); //strlen(s) is used here as well but doesn't change outcome 
     dyn_s = s; 
     dyn_s[strlen(s)] = '\0'; 
     puts(dyn_s); 
     return 0; 
    } 

Best:

#include <stdio.h> 
#define BUF_SIZE 80 

int 
main(int argc, char *argv[]) 
{ 
     char s[BUF_SIZE]; 
     int ln; 
     puts("Enter String"); 
     fgets(s, BUF_SIZE, stdin); // Use fgets (our "cin"): NEVER "gets()" 

     int ln = strlen(s); 
     char *dyn_s = (char*) malloc (ln+1); 
     strcpy (dyn_s, s); 
     puts(dyn_s); 
     return 0; 
    } 
+0

Besser noch: 'char * dyn_s = malloc (ln + 1);'. Beachten Sie, dass 'fgets()' das abschließende '\ n'' im Puffer belässt; 'gets()' verwirft es (aber 'gets()' ist immer noch katastrophal schlecht). –

+0

Cool! Vielen Dank. Irgendwelche großen Ressourcen, zu denen Sie Verbindungen haben, bezüglich des Verhaltens der häufig verwendeten IO-Funktionen? – ceod

+0

Und neben 'cast'' malloc() 'Ergebnis entfernen, überprüfen Sie, ob Sie keinen' NULL' Wert erhalten haben. 'char * dyn_s = malloc (ln + 1); if (! dyn_s) {printf ("Nein mem! \ n"); exit (EXIT_FAILURE);} 'oder können Sie einen weiteren Segmentierungsfehler erhalten. –

1

Ihre scanf("%s", s); wird als Kommentar gekennzeichnet. Das bedeutet, dass s nicht initialisiert ist. Wenn diese Zeile ln = strlen(s); ausgeführt wird, erhalten Sie einen Seg-Fehler.

Es hilft immer, einen Zeiger auf NULL zu initialisieren, und dann vor dem Verwenden des Zeigers auf Null zu testen.

+0

Danke! Wird die Initialisierung des NULL-Zeigers häufiger ausführen und testen. Ich glaube nicht, dass ich den Scanf Teil bekomme. Sollte das scanf nicht auch scheitern? Immerhin ist der Zeiger zu nichts initialisiert und kann auf eine willkürliche und illegale Position als Startposition der Kette zeigen, daher ein Seg-Fehler? Ich habe es auskommentiert, da es auch zu Seg-Fehlern führte. Oder habe ich etwas nicht verstanden? – ceod

+0

Diese Antwort ist ** falsch **. Wenn Sie diesen Zeiger auf NULL initialisieren, wird das auch dazu führen, dass UB - NULL nie dereferenziert wird, nicht einmal von scanf ... –

+0

Ich teste meine Zeiger, um zu sehen, ob sie auf Null gesetzt sind. Wenn vor der Verwendung auf Null initialisiert wird, besteht eine vernünftige Möglichkeit, dass der Zeiger nicht bereits einem gültigen Speicher zugewiesen ist. – octopusgrabbus

1

Noch besser

#include <stdio.h> 
int 
main(void) 
{ 
    char *line = NULL; 
    size_t count; 
    char *dup_line; 

    getline(&line,&count, stdin); 
    dup_line=strdup(line); 

    puts(dup_line); 

    free(dup_line); 
    free(line); 

    return 0; 
} 
+0

Hallo! Ich habe nie die Funktionen getline() und strdup() benutzt. Ich glaube nicht, dass ich sie auch schon einmal gesehen habe. Danke, dass du sie mir vorgestellt hast;). Umm leider läuft dein Code in einen Seg Fehler! – ceod

+0

Seltsam. Warnung vor impliziter Deklaration, korrekte Arbeit für mich. GNU/Linux-System, gcc 4.6.3. – KAction

+0

'line' sollte mit NULL initialisiert werden. Ja, C kann grausam sein. – KAction

1
char *s does not have some memory allocated . You need to allocate it manually in your case . You can do it as follows 
s = (char *)malloc(100) ; 

Dies würde nicht zu Segmentation fault Fehler führen, da Sie nicht mehr