2009-08-18 8 views
2

Ce code compile bien mais donne une erreur de segmentation en cours d'exécution? Quelqu'un peut-il dire pourquoi?erreur d'exécution de chaîne simple dans 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

Le compilateur fera * une * vérification pour vous, mais il n'y a aucun moyen d'éliminer tous les programmes potentiellement dangereux, au moins pas en C. Beaucoup d'autres langues sont beaucoup plus protecteurs, mais la plupart d'entre eux ne vous permettent pas d'accéder à la mémoire arbitraire comme le fait C. – quark

Répondre

13

Vous espace alloué pour un seul pointeur, s1, mais pas les octets pointé par s1.

Une solution est d'allouer dynamiquement la mémoire pour s1:

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

Gardez à l'esprit que vous avez besoin d'allouer un octet de mémoire (le +1 dans l'appel à malloc) que le nombre de caractères s2 car il existe un NULL octet implicite à la fin. Pour plus d'informations, voir C Memory Management (Stack Overflow) pour plus d'informations.

+1

Puisque s2 est un tableau alloué statiquement, vous pouvez utiliser sizeof() pour obtenir sa taille incluant le terminateur nul. strlen() + 1 est correct pour le cas général, bien sûr. –

+1

Voici d'autres conseils dont je ne voulais pas encombrer la réponse avec: 1) _Do_ vérifier que 's1! = NULL' et 2) _Do_ appel' free' sur 's1' dans tout code qui ne retourne pas immédiatement . –

+0

De plus, le pointeur 's1' ne pointe nulle part car il n'est pas initialisé. Quand il est initialisé, il doit pointer sur suffisamment d'espace pour stocker la chaîne. L'espace peut provenir de 'malloc()'; ça pourrait venir d'ailleurs. –

4

Vous n'avez pas alloué de mémoire pour s1. Vous avez un pointeur sur s1 mais pas de mémoire allouée à strcpy pour copier la valeur de s2 dans.

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

strcpy(s1, s2); 
+2

Vous avez une erreur "off-by-one" dans votre appel malloc. –

+0

Et 'strcpy' ne prend que 2 arguments. Peut-être que vous pensez à 'strncpy'. –

+0

Merci Andrew, corrigé maintenant. Ah, vous avez raison Sean, va modifier pour résoudre. – nathan

1

Vous devez allouer la destination (et using namespace std; n'est pas C mais C++, le reste du code est C).

2

Le problème est que s1 n'a aucune mémoire associée. strcpy n'appelle pas malloc().

Vous pouvez soit faire:

char s1[10];

ou

char *s1 = malloc(10);

+2

Mais strdup le fait, sur les systèmes qui le supportent. :-) –

3

Vous avez attribué aucune mémoire s1. C'est un pointeur vers rien.

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

Notez que sizeof (s2) fonctionne car s2 est un tableau. Si c'est un pointeur, vous avez besoin de strlen (s2) +1. – AProgrammer

0

Vous devez allouer de la mémoire au pointeur s1. Si vous ne le faites pas, il pointe vers un endroit inconnu et arrive ainsi à la faute de segmentation. Le code correct doit être:

#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) n'est pas nécessaire, puisque sizeof (char) == 1 est garanti par la norme. Le cast (char *) n'est pas non plus nécessaire puisqu'il s'agit de C, et les pointeurs de void sont implicitement convertibles en n'importe quel autre type de pointeur. –

+0

@Tyler McHenry désolé, j'ai appris à l'école que c'était nécessaire. Quoi qu'il en soit, à propos de la partie sizeof, je suppose qu'il devrait être là au cas où l'auteur changerait le code en un autre type. – Guilherme

+1

Ensuite, faites juste 'sizeof (s2 [0])' ou 'sizeof (* s2)' –

2

Ce qu'ils ont tous dit, vous devez allouer l'espace pour s1. Ce que tout le monde a mis en ligne fonctionnera très bien, mais si vous voulez un moyen plus simple d'allouer l'espace pour une chaîne existante et le copier dans un nouveau pointeur puis utilisez strdup comme ceci:

#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; 
} 

Quelqu'un a mentionné strdup plus tôt, ce serait un moyen de l'utiliser. La plupart des systèmes devraient le supporter puisqu'il est dans les librairies C standard. Mais apparemment, certains ne le font pas. Donc, si elle renvoie une erreur, écrivez la vôtre en utilisant la méthode déjà mentionnée, ou utilisez simplement la méthode déjà mentionnée;)

2

Personne n'a encore signalé le potentiel de strdup (String Duplicate) pour résoudre ce problème. Le code de compilation ne garantit pas vraiment un programme stable.

#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; 
}