2009-08-18 14 views
2

Dieser Code wird zwar kompiliert, gibt aber beim Ausführen einen Segmentierungsfehler aus. Kann jemand sagen warum?einfache Zeichenfolge Laufzeitfehler in C?

#include <stdio.h> 
#include <string.h> 
#include <math.h> 

int main() { 
    const char s2[] = "asdfasdf"; 
    char* s1; 

    strcpy(s1, s2); 
    printf("%s", s1); 

    return 0; 
} 
+0

Code-Kompilierung garantiert nicht wirklich ein stabiles Programm.Der Compiler wird * einige * für Sie überprüfen, aber es gibt keine Möglichkeit, alle möglichen unsicheren Programme zu eliminieren, zumindest nicht in C. Viele andere Sprachen sind viel schützender, aber die meisten von ihnen lassen Sie nicht auf beliebigen Speicher zugreifen Weg C tut es. – quark

Antwort

13

Sie zugewiesenen Platz für einen einzelnen Zeiger, s1, aber nicht der Bytes zeigte auf von s1.

ist eine Lösung Speicher zuweisen dynamisch für s1:

s1 = (char *)malloc(strlen(s2) + 1); 
strcpy(s1, s2); 

Beachten Sie, dass Sie ein weiteres Byte Speicher (die +1 in dem Aufruf von malloc) als die Anzahl der Zeichen zuweisen müssen in s2 weil am Ende ein implizites NULL Byte ist.

Weitere Informationen finden Sie unter C Memory Management (Stack Overflow).

+1

Da s2 ein statisch zugewiesenes Array ist, können Sie sizeof() verwenden, um seine Größe einschließlich des Null-Terminators zu erhalten. strlen() + 1 ist natürlich für den allgemeinen Fall korrekt. –

+1

Hier sind einige weitere Tipps, die ich nicht mit der Antwort durcheinander bringen wollte: 1) _Do_ check dass 's1! = NULL' und 2) _Do_' 'free' auf' s1' in jedem Code, der nicht sofort zurückgibt . –

+0

Darüberhinaus zeigt der Zeiger 's1' nicht irgendwobestimmt, weil er nicht initialisiert ist. Wenn es initialisiert wird, muss es auf genügend Speicherplatz zeigen, um die Zeichenfolge zu speichern. Das Leerzeichen könnte aus 'malloc()' kommen; es könnte von anderswo kommen. –

4

Sie haben keinen Speicher für s1 reserviert. Sie haben einen Zeiger auf s1, aber keinen Speicher, der für den strcpy reserviert ist, um den Wert von s2 in zu kopieren.

char *s1 = malloc(strlen(s2) + 1); 

strcpy(s1, s2); 
+2

Sie haben einen Fehler in Ihrem malloc-Aufruf. –

+0

Und 'strcpy' benötigt nur 2 Argumente. Vielleicht denkst du an "strncpy". –

+0

Danke Andrew, jetzt behoben. Ah, du hast Recht, Sean, wird bearbeitet, um zu beheben. – nathan

1

Sie müssen das Ziel zuweisen (und using namespace std; ist nicht C, sondern C++, der Rest des Codes ist C).

2

Das Problem ist, dass s1 keinen Speicher zugeordnet hat. strcpy ruft nicht malloc().

Sie könnten entweder tun:

char s1[10];

oder

char *s1 = malloc(10);

+2

Aber straddup tut, auf Systemen, die es unterstützen. :-) –

3

Sie haben kein Gedächtnis s1 nicht zugeordnet. Es ist ein Zeiger auf nichts.

char* s1 = malloc(sizeof(s2)); 
strcpy(s1, s2); 
printf("%s", s1); 
free(s1); 
+2

Beachten Sie, dass sizeof (s2) funktioniert, weil s2 ein Array ist. Wenn es ein Zeiger ist, brauchen Sie strlen (s2) +1. – AProgrammer

0

Sie müssen dem Zeiger s1 Speicher zuweisen. Wenn Sie das nicht tun, wird es irgendwo unbekannt angezeigt und kommt damit zum Segmentierungsfehler. Der korrekte Code sollte sein:

#include <stdio.h> 
#include <string.h> 
#include <math.h> 

int main() { 
    const char s2[] = "asdfasdf"; 
    char* s1 = malloc(21 * sizeof(s2[0])); 
    strcpy(s1,s2); 
    printf("%s",s1); 
    return 0; 
} 
+1

sizeof (char) ist nicht notwendig, da sizeof (char) == 1 vom Standard garantiert wird. Die (char *) Umwandlung ist auch nicht notwendig, da dies C ist und void-Zeiger implizit in jede andere Art von Zeiger umgewandelt werden können. –

+0

@Tyler McHenry Entschuldigung, ich habe in der Schule gelernt, dass es notwendig war. Wie auch immer, über die Größe des Teils denke ich, dass es dort sein sollte, falls der Autor den Code in einen anderen Typ ändert. – Guilherme

+1

Dann mach es einfach 'sizeof (s2 [0])' oder 'sizeof (* s2)' –

2

Was sie alle gesagt haben, müssen Sie den Platz für s1 zuweisen. Was für alle anderen arbeiten geschrieben hat ganz gut, aber wenn Sie einen einfacheren Weg wollen für einen vorhandenen String Speicherplatz zuweisen und sie in einen neuen Zeiger kopieren dann strdup wie folgt verwenden:

#include <stdio.h> 
#include <string.h> 
#include <math.h> 

using namespace std; 

int main() { 
    const char s2[] = "asdfasdf"; 
    char* s1; 

    s1 = strdup(s2); 
    printf("%s", s1); 

    return 0; 
} 

Jemand erwähnte strdup früher, das wäre ein Weg, es zu benutzen. Die meisten Systeme sollten es unterstützen, da es in den Standard-C-Bibliotheken enthalten ist. Aber anscheinend tun einige nicht. Also, wenn es einen Fehler zurückgibt, schreibe entweder deinen eigenen mit der bereits erwähnten Methode, oder benutze einfach die bereits erwähnte Methode;)

2

Niemand hat bisher auf das Potential von strdup (String Duplicate) hingewiesen, um dieses Problem zu lösen.

#include <stdio.h> 
#include <string.h> 
#include <math.h> 

using namespace std; 

int main() { 
    const char s2[] = "asdfasdf"; 
    char* s1; 

    s1 = strdup(s2); // Allocates memory, must be freed later. 
    printf("%s", s1); 

    free(s1);   // Allocated in strdup, 2 lines above 
    return 0; 
}