Erreur de segmentation en C

Résolu/Fermé
LCoileux - 8 avril 2010 à 18:35
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 - 8 avril 2010 à 21:48
Bonjour,
débutant en langage C, je veux faire un petit programme, et je bloque dejà au debut...
Voila mon code:

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


typedef struct Element Element;

struct Element{
    char *nomElement;
    int hauteurElement;
};

Element *creerElement(char *nom, int h){
    Element *element;
    strcpy(element->nomElement, nom);
    element->hauteurElement = h;
    return(element);
}

int main(void){
    Element *elt;
    char *tab = "element n° 1";
    elt = creerElement(tab, 10);
    printf("Element de nom %s et de hauteur %d cree !\n", elt->nomElement, elt->hauteurElement);
    return 1;
}


Tout compile, c'est bon, mais quand je le lance, j'obtiens une erreur de segmentation. Après recherche, il semblerait que ca provienne de la fonction strcpy.
Je pense que cela vient du fait que nomElement n'est pas de taille suffisante pour recevoir la chaine de caractères, et que donc je dois lui donner une taille assez grande. Seulement je ne voie pas trop comment faire...
J'ai essayé de passer par un tableau intermédiaire, de faire un malloc,...mais ca n'a pas fonctionné. Comment dois-je faire ?

Merci

4 réponses

chuka Messages postés 965 Date d'inscription samedi 11 octobre 2008 Statut Membre Dernière intervention 29 juillet 2010 378
Modifié par chuka le 8/04/2010 à 20:03
Salut,
il y a 3 façons d'initialiser les pointeur:
-Allocation de mémoire par malloc ((entre autre) (char*m=(char*)malloc(sizeof (char)*20)->alloue sur le tas une zone mémoire de 20 octets, m a pour adresse le premier element)
-Initialisation avec une valeur (int*p=32)
-Initilisation avec une adresse (unsigned short*w=0x2365;unsigned short*ww;ww=w)(ww et w pointe alors sur la meme adresse memoire)

Donc quand tu ecris:
Element *creerElement(char *nom, int h){
Element *element; //(element n'a jamais d'adresse memoire alloué donc plantage pour la suite...car à quelle adresse memoire aller lire ou ecrire!!
strcpy(element->nomElement, nom);//voir ci-dessus...et il faudrait aussi creer un espace memoire pour ton char* ou passer directement l'adresse..
element->hauteurElement = h;
return(element);
}
Element *creerElement(char *nom, int h){
Element *element=(Element*)malloc(sizeof(Element));
element->nomElement=nom;//Attention element->nomElement et nom on //alors la meme adresse!! modification des données pointées de l'un modifie //l'autre
element->hauteurElement = h;
return(element);
}
ou sinon
Element *creerElement(char *nom, int h){
Element *element=(Element*)malloc(sizeof(Element));
char*m=(char*)malloc(sizeof(char)*(strlen(nom)+1));
strcpy(m, nom);
element->nomElement=m;
//dans ce cas modification des données de //l'un ne modifie pas les données de l'autres!!
element->hauteurElement = h;
return(element);
}
J'ai pas testé mais cela devrait fonctionner!!
@+
Ce n'est pas parce que certaines choses semblent inexplicables, qu'il faut faire semblant de les expliquer!
0
tatou_38 Messages postés 1928 Date d'inscription vendredi 21 avril 2006 Statut Membre Dernière intervention 5 août 2015 120
8 avril 2010 à 20:56
Utiliser un pointeur non initialiser est mortel, tu viens de le découvrir à tes dépens :

Element *creerElement(char *nom, int h){
Element *element;
strcpy(element->nomElement, nom);
element->hauteurElement = h;
return(element);
}

strcpy copie une chaîne de caractère dans element->nomElement, soit.
Or element est déclaré comme étant un pointeur sur un objet de type Element, mais quel objet ?? Et bien aucun puisque tu ne l'as pas défini, c'est à dire que element pointe sur n'importe quoi ==> PLANTAGE assuré !

il eut fallu par exemple faire :

Element *element = malloc( sizeof(Element) );
strcpy(element->nomElement, nom);

el désallouer element quand tu n'en auras plus besoin !
0
Merci, ca fonctionne ! :)
En espérant ne plus avoir d'erreurs :p
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
8 avril 2010 à 21:48
Bonjour,

Element *elt;
Comme dit plus haut, cette instruction ne réserve pas de zone qui pourra recevoir des données. Pour ceci il faut utiliser malloc.
Par exemple : elt=malloc(taille*sizeof(Element));
Ou plus générique : elt = malloc(taille*sizeof(*elt));

Ensuite, il ne faut pas oublier de libérer les ressources avant la fin du programme.
Ceci est très simple : free(elt);

Et enfin, un petit point de détail :
return 1;
C'est return 0; qu'il faut mettre à la fin pour signaler que le programme s'est bien déroulé.

Cdlt,
0