[langage C] segmentation fault
Résolu/Fermé
Benja85
Messages postés
4
Date d'inscription
mercredi 20 septembre 2006
Statut
Membre
Dernière intervention
22 septembre 2006
-
21 sept. 2006 à 00:14
mamiemando Messages postés 33363 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 16 novembre 2024 - 12 mars 2011 à 00:45
mamiemando Messages postés 33363 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 16 novembre 2024 - 12 mars 2011 à 00:45
A voir également:
- Erreur de segmentation c
- Erreur 0x80070643 - Accueil - Windows
- Erreur 0x80070643 Windows 10 : comment résoudre le problème de la mise à jour KB5001716 - Accueil - Windows
- Erreur 1001 outlook - Accueil - Bureautique
- Erreur 3000 france tv - Forum Lecteurs et supports vidéo
- Erreur de lecture reconnecté en 3s - Forum TV & Vidéo
8 réponses
tafiscobar
Messages postés
1277
Date d'inscription
jeudi 7 décembre 2000
Statut
Contributeur
Dernière intervention
26 février 2009
177
22 sept. 2006 à 10:26
22 sept. 2006 à 10:26
salut, tout d'abord s2 est un pointeur sur un const char. Donc sizeof s2 te donne la taille du pointeur ie 4octets et non la taille de ta chaine (si c'est vrai, le compilateur n'est pas normé iso, ce n'est pas le comportement de sizeof sinon il n'y aurait pas de strlen).
Ensuite, si tu alloues de la mémoire dans la fonction my_strcpy, ben malloc te retourne un pointeur local et donc quand tu sors de ta fonction, ton pointeur local est perdu et donc d'ou le segmentation fault. Le malloc est fait par l'utilisateur et non dans la fonction strcpy.
Ensuite strcpy retourne le pointeur sur un char ie char* et non un char. Ta fonction devrait etre:
Ensuite, si tu alloues de la mémoire dans la fonction my_strcpy, ben malloc te retourne un pointeur local et donc quand tu sors de ta fonction, ton pointeur local est perdu et donc d'ou le segmentation fault. Le malloc est fait par l'utilisateur et non dans la fonction strcpy.
Ensuite strcpy retourne le pointeur sur un char ie char* et non un char. Ta fonction devrait etre:
char* my_strcpy (char* dest, const char* src) { int i; for (i = 0; src[i]!='\0'; ++i) dest[i] = src[i]; dest[i] = '\0'; return dest; }
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
22 sept. 2006 à 08:56
22 sept. 2006 à 08:56
après test chez moi, en fait, il n'y a pas d'erreur.
Je pense donc que cela viens d'ailleur
Je pense donc que cela viens d'ailleur
Benja85
Messages postés
4
Date d'inscription
mercredi 20 septembre 2006
Statut
Membre
Dernière intervention
22 septembre 2006
22 sept. 2006 à 09:57
22 sept. 2006 à 09:57
Je me suis débrouillé finalement, en enlevant ce qui posait problème, j'arrive à un truc de ce genre :
char* my_strcpy (char* s1, const char* s2)
{
int i;
for (i=0; s2[i] != '\0'; i++) s1[i] = s2[i];
return s1;
}
Ainsi je ne me soucie plus du problème de l'allocation de mémoire.
Il est tout de même logique que avant d'appeler la fonction my_strcpy, il faut faire de la place, alors j'ai fais ca dans ma méthode main (pour les tests uniquement) :
char* src = "Tests";
char* dst = malloc(sizeof(src));
printf("%s\n", my_strcpy(dst, src));
Voilà tout simplement :) merci à vous !
char* my_strcpy (char* s1, const char* s2)
{
int i;
for (i=0; s2[i] != '\0'; i++) s1[i] = s2[i];
return s1;
}
Ainsi je ne me soucie plus du problème de l'allocation de mémoire.
Il est tout de même logique que avant d'appeler la fonction my_strcpy, il faut faire de la place, alors j'ai fais ca dans ma méthode main (pour les tests uniquement) :
char* src = "Tests";
char* dst = malloc(sizeof(src));
printf("%s\n", my_strcpy(dst, src));
Voilà tout simplement :) merci à vous !
mamiemando
Messages postés
33363
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
16 novembre 2024
7 801
23 sept. 2006 à 11:21
23 sept. 2006 à 11:21
L'erreur de segmentation était à mon avis plutôt dûe au fait qu'il fallait écrire :
Si ton my_strcpy retourne le char *, rien ne t'empêche de faire le free dessus à l'extérieur.
Je n'ai pas testé mais ça doit marcher ça, non ?
char *dst = (char *) malloc(sizeof(char)*strlen(src));
Si ton my_strcpy retourne le char *, rien ne t'empêche de faire le free dessus à l'extérieur.
#include <stdlib.h> #include <string.h> #include <stdio.h> char* my_strcpy (char* dest, const char* src) { int i; dest = (char *) malloc(sizeof(char)*strlen(src)); for (i = 0; src[i]!='\0'; ++i) dest[i] = src[i]; dest[i] = '\0'; return dest; } int main(){ char *src = "tapir",dst; my_strcpy(dst,src); printf("dst = %s\n",dst); free(dst); getchar(); // pour les windowsiens return 0; }
Je n'ai pas testé mais ça doit marcher ça, non ?
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
21 sept. 2006 à 08:32
21 sept. 2006 à 08:32
salut.
Je suis pas très calé en allocation de mémoire, mais je vais essayer de t'aider.
Je ne suis pas sur que sizeof s2 te donne la longueur de la chaine.
Tout d'abord, pour debugger, fait un printf de "sizeof s2" voir si cela correspond bien à la longueur de s2. Si oui, ne manquerai t'il pas une largeur de type ?
tu peux peut être remplacer sizeof s2 par strlen(s2).
Bonne chance
Je suis pas très calé en allocation de mémoire, mais je vais essayer de t'aider.
Je ne suis pas sur que sizeof s2 te donne la longueur de la chaine.
Tout d'abord, pour debugger, fait un printf de "sizeof s2" voir si cela correspond bien à la longueur de s2. Si oui, ne manquerai t'il pas une largeur de type ?
tu peux peut être remplacer sizeof s2 par strlen(s2).
Bonne chance
Benja85
Messages postés
4
Date d'inscription
mercredi 20 septembre 2006
Statut
Membre
Dernière intervention
22 septembre 2006
21 sept. 2006 à 10:12
21 sept. 2006 à 10:12
sizeof (s2) me donne bien la longueur de s2 (avec le dernier char \0).
Le problème se situe ailleurs, ça doit être une histoire de pointeur mais je nage un peu pour le moment là dedans...
Le problème se situe ailleurs, ça doit être une histoire de pointeur mais je nage un peu pour le moment là dedans...
carkiasis
Messages postés
67
Date d'inscription
jeudi 17 février 2005
Statut
Membre
Dernière intervention
26 avril 2007
28
>
Benja85
Messages postés
4
Date d'inscription
mercredi 20 septembre 2006
Statut
Membre
Dernière intervention
22 septembre 2006
21 sept. 2006 à 21:53
21 sept. 2006 à 21:53
Si tu travailles sous linux, tu peux utiliser ddd (je ne sais pas si ce prog existe aussi sous Windows). Cela te permettra de voir à quelle ligne se situe le segmentation fault...
Bon courage
Bon courage
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
22 sept. 2006 à 08:49
22 sept. 2006 à 08:49
Oula !
J'avais pas fait gaffe !
les s1[i] en dehors du for
à éviter.
vérifie sa valeur avant de l'utiliser, il est possible que le problème vienne de là
J'avais pas fait gaffe !
les s1[i] en dehors du for
à éviter.
vérifie sa valeur avant de l'utiliser, il est possible que le problème vienne de là
arth
Messages postés
9374
Date d'inscription
mardi 27 septembre 2005
Statut
Contributeur
Dernière intervention
16 décembre 2016
1 291
23 sept. 2006 à 11:46
23 sept. 2006 à 11:46
en même temps essayer de retourner des chaines de caractères en c ca devient risqué ^^
mamiemando
Messages postés
33363
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
16 novembre 2024
7 801
24 sept. 2006 à 11:33
24 sept. 2006 à 11:33
Je ne vois pas pourquoi. En fait de manière générale on essaye juste de mettre le calloc/malloc dans le même horizon que le free (ce qui n'est pas le cas de l'exemple que j'ai donné) et c'est pour ça que la version de tafiscobar est plus propre. Il faut juste avec sa version penser à allouer la chaine dest dans le main (et à la désallouer).
Hxyp
Messages postés
401
Date d'inscription
vendredi 28 janvier 2011
Statut
Membre
Dernière intervention
27 avril 2014
54
10 mars 2011 à 21:31
10 mars 2011 à 21:31
Salut,
mamiemando ce n'était pas un mauvais exemple :
#include <stdio.h>
#include <stdlib.h>
char *StrCpy(char *dest,const char *src)
{
int i,x;
for(x=0;src[x];x++);
dest=calloc(sizeof(char),x);
for(i=0;src[i];i++) dest[i]=src[i];
return dest;
}
int main()
{
char *src="hello world";
char *des;
des=StrCpy(des,src);
printf("%s\n",des);
free(des);
return EXIT_SUCCESS;
}
mamiemando ce n'était pas un mauvais exemple :
#include <stdio.h>
#include <stdlib.h>
char *StrCpy(char *dest,const char *src)
{
int i,x;
for(x=0;src[x];x++);
dest=calloc(sizeof(char),x);
for(i=0;src[i];i++) dest[i]=src[i];
return dest;
}
int main()
{
char *src="hello world";
char *des;
des=StrCpy(des,src);
printf("%s\n",des);
free(des);
return EXIT_SUCCESS;
}
mamiemando
Messages postés
33363
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
16 novembre 2024
7 801
Modifié par mamiemando le 11/03/2011 à 08:13
Modifié par mamiemando le 11/03/2011 à 08:13
Dans ton code :
- inutile de faire un calloc si c'est pour réaffecter les n caractères de la chaîne. Il ne sert vu ton code en réalité que pour le \0 final. Un malloc serait plus rapide, il faut juste penser à mettre le '\0' à la main.
- la boucle for que tu utilises est juste mais si tu regardes le code de la libc on utilisera plutôt ce genre de boucle, légèrement plus rapide car elle engendre moins d'opérations :
- le plus gros soucis si on compare ton StrCpy (qui devrait s'écrire strcpy pour suivre les conventions du C où tout est en minuscule, et disons my_strcpy pour le distinguer de celui de la libc) c'est qu'il fait une allocation à l'insu du développeur. Si on regarde ton main, pour éviter un memory leak tu es obligé de faire un free. Normalement un free est associé à un malloc (ou tout autre fonction d'allocation mémoire). Ainsi ça devrait plutôt ressembler à ceci :
En effet, strcpy n'a pas pour vocation d'allouer de la mémoire. Ainsi, même si ta solution est algorithmiquement et fonctionnellement juste, elle est contestable en terme d'architecture. C'est ce que je tentais d'expliquer dans mon précédent message, je ne sais pas si c'est plus clair.
- inutile de faire un calloc si c'est pour réaffecter les n caractères de la chaîne. Il ne sert vu ton code en réalité que pour le \0 final. Un malloc serait plus rapide, il faut juste penser à mettre le '\0' à la main.
- la boucle for que tu utilises est juste mais si tu regardes le code de la libc on utilisera plutôt ce genre de boucle, légèrement plus rapide car elle engendre moins d'opérations :
while(*pdst++ = *psrc++);
- le plus gros soucis si on compare ton StrCpy (qui devrait s'écrire strcpy pour suivre les conventions du C où tout est en minuscule, et disons my_strcpy pour le distinguer de celui de la libc) c'est qu'il fait une allocation à l'insu du développeur. Si on regarde ton main, pour éviter un memory leak tu es obligé de faire un free. Normalement un free est associé à un malloc (ou tout autre fonction d'allocation mémoire). Ainsi ça devrait plutôt ressembler à ceci :
int main(){ const char *src = "hello world"; char *dst = malloc((1+strlen(src))*sizeof(char)); dst = StrCpy(dst, src); printf("%s\n",dst); free(dst); return 0; }
En effet, strcpy n'a pas pour vocation d'allouer de la mémoire. Ainsi, même si ta solution est algorithmiquement et fonctionnellement juste, elle est contestable en terme d'architecture. C'est ce que je tentais d'expliquer dans mon précédent message, je ne sais pas si c'est plus clair.
Hxyp
Messages postés
401
Date d'inscription
vendredi 28 janvier 2011
Statut
Membre
Dernière intervention
27 avril 2014
54
12 mars 2011 à 00:15
12 mars 2011 à 00:15
Merci pour toutes ces précisions et explications, le while(*pdst++ = *psrc++); j'y aurai jamais pensé et je trouve ça tout simplement génial !!
Oui j'avais mal interprété le sens du "mauvais exemple", c'est clair que ça pourrait poser un problème si on oubli de faire un free en ignorant que StrCpy fait une allocation
Oui j'avais mal interprété le sens du "mauvais exemple", c'est clair que ça pourrait poser un problème si on oubli de faire un free en ignorant que StrCpy fait une allocation
mamiemando
Messages postés
33363
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
16 novembre 2024
7 801
12 mars 2011 à 00:45
12 mars 2011 à 00:45
Pas de soucis, bonne continuation ;-)
22 sept. 2006 à 22:18
Ca roule :p
10 mars 2011 à 20:27