IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Problème d'allocation mémoire (structures et pointeurs)


Sujet :

C

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2009
    Messages : 389
    Points : 192
    Points
    192
    Par défaut Problème d'allocation mémoire (structures et pointeurs)
    Bonjour,
    j'essaye d'implémenter une structure permettant de gérer des polynômes. J'utilise des monômes comme étant des maillons d'une liste chainée, cette dernière représentant le polynôme. Je rencontre des problèmes d'allocation mémoire avec une fonction qui permet d'additionner deux polynômes.

    Je ne trouve pas mon erreur, car la fonction ne commence même pas, quand je teste un printf en début de fonction.

    L'erreur que le compilateur me retourne est "segmentation fault", et je n'arrive pas à saisir ce qui ne va pas avec mes malloc.

    Merci de votre aide.

    Voici mon code :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
     
     
    polynome creer(float coeff, float degre) {
    	polynome p = malloc(sizeof(*p));
    	p->coeff = coeff;
    	p->degre = degre;
    	p->suiv = NULL;
    	return p;
    }
     
    void afficher(polynome p) {
     
    	while (p != NULL) {
    		printf("%2.2fx^%2.2f", p->coeff, p->degre);
    		if (p->suiv != NULL) {
    			printf("+");
    		}
    		p = p->suiv;
    	}
    	printf("\n");
    }
     
    polynome insererEnTete(polynome p, float coeff, float degre) {
    	polynome tmp = malloc(sizeof(*tmp));
    	tmp->coeff = coeff;
    	tmp->degre = degre;
    	tmp->suiv = p;
    	return tmp;
    }
     
    polynome insererEnQueue(polynome l, float coeff, float degre) {
    	polynome tmp = l;
    	if (l) {
    		while (l->suiv)
    			l = l->suiv;
    		//NULL peut etre remplace par 0 (zero)
    		l->suiv = insererEnTete(NULL, coeff, degre);
    		return tmp;
    	}
    	return insererEnTete(NULL, coeff, degre);
    }
     
    polynome additionner(polynome p1, polynome p2) {
    	polynome tmp = malloc(sizeof(*tmp));
    	polynome premier = malloc(sizeof(*premier));
     
    	polynome po1 = malloc(sizeof(*po1));
    	po1 = p1;
    	polynome po2 = malloc(sizeof(*po2));
    	po2 = p2;
     
    	if (po1->degre > po2->degre) {
    		premier = creer(p1->coeff, p1->degre);
    		po1 = po1->suiv;
    	} else if (po1->degre < po2->degre) {
    		premier = creer(po2->coeff, po2->degre);
    		po2 = po2->suiv;
    	} else {
    		premier = creer(po1->coeff + po2->coeff, po1->degre + po2->degre);
    		po1 = po1->suiv;
    		po2 = po2->suiv;
    	}
    	tmp = premier;
     
    	while (po1 != NULL && po2 != NULL) {
     
    		if (po1->degre > po2->degre) {
    			tmp->degre = p1->degre;
    			tmp->coeff = p1->coeff;
    			tmp = tmp->suiv;
    			po1 = po1->suiv;
    		} else if (po2->degre > po1->degre) {
    			tmp->degre = po2->degre;
    			tmp->coeff = po2->coeff;
    			tmp = tmp->suiv;
    			po2 = po2->suiv;
    		} else if (po1->degre == po2->degre) {
    			tmp->coeff = po1->coeff + po2->coeff;
    			tmp->degre = po1->degre;
    			po1 = po1->suiv;
    			po2 = po2->suiv;
    			tmp = tmp->suiv;
    		}
     
    		if (po1 == NULL) {
    			po1->coeff = 0;
    			po1->degre = 0;
    		}
    		if (po2 == NULL) {
    			po2->coeff = 0;
    			po2->degre = 0;
    		}
    	}
    	tmp->suiv = NULL;
    	return premier;
    }
     
    int main(void) {
     
    	polynome p1 = malloc(sizeof(polynome));
    	polynome p2 = malloc(sizeof(polynome));
    	polynome p3 = malloc(sizeof(polynome));
     
    	monome m1, m2, m3, m4;
    	m1.coeff = 3;
    	m1.degre = 2;
    	m1.suiv = &m2;
     
    	m2.coeff = 1;
    	m2.degre = 0;
    	m2.suiv = NULL;
     
    	p1 = &m1;
     
    	m3.coeff = 4;
    	m3.degre = 3;
    	m3.suiv = &m4;
     
    	m4.coeff = 2;
    	m4.degre = 1;
    	m4.suiv = NULL;
     
    	p2 = &m3;
     
    	printf("p1:");
    	afficher(p1);
    	printf("p2:");
    	afficher(p2);
     
    	p3 = additionner(p1, p2);
    	printf("p1+p2=");
    	afficher(p3);
    	return 0;
    }


  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 369
    Points
    50 369
    Par défaut
    on peut voir la définition de polynome.

    J'ai l'impression que c'est un pointeur mais je n'en suis pas sûr. En tout cas, si c'est un pointeur, les malloc en début de main() sont faux car il allouent la taille d'un pointeur (4 octets) au lieu d'allouer la taille d'un polynome.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    polynome p1 = malloc(sizeof(polynome));

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2009
    Messages : 389
    Points : 192
    Points
    192
    Par défaut
    Oui bien sur, j'ai complètement oublié la structure du polynôme!

    La voici :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    typedef struct monome {
    	float coeff;
    	float degre;
    	struct monome *suiv;
    } monome, *polynome;

    pour l'allocation, j'ai pris l'habitude de faire comme ça, c'est faux? Pourtant, le pointeur est de type polynome lors de l'initialisation?

  4. #4
    Membre éclairé
    Avatar de Pouet_forever
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    671
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 671
    Points : 842
    Points
    842
    Par défaut
    Tu fais plein de malloc mais tu les déréférences après, ce qui fait que tu as des grosses fuites de mémoire.
    Tes mallocs dans la fonction main sont faux, cf réponse de ram-0000.
    Tu pourrais tester le retour de tes fonctions malloc.
    Je ne comprend pas bien comment tu veux faire ton addition, tu pourrais m'éclaircir ? je pense que tu peux faire largement plus simple en cherchant les polynomes de même degré, en les additionnant et en mettant le résultat dans une nouvelle variable. Ca serait plus simple d'utiliser un tableau je pense.

    Pour ton segfault, il se situe surtout à ce niveau là : tmp = tmp->suiv;
    Tu affectes la valeur de tmp->suiv à tmp mais au 2ème tour de boucle tmp == NULL donc accéder à tmp->degre te fait un segfault.

  5. #5
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 369
    Points
    50 369
    Par défaut
    Citation Envoyé par floctc Voir le message
    pour l'allocation, j'ai pris l'habitude de faire comme ça, c'est faux? Pourtant, le pointeur est de type polynome lors de l'initialisation?
    Oui, c'est correct si le type est un type plein (comprendre une structure). Dans ton cas, ton type est un pointeur et donc il vaut 4 octets (ou 8 selon les architectures) et tu l'as oublié lors de l'écriture de ton code. Lorsque tu fais ton malloc(), tu alloues 4 octets au lieu d'allouer la taille de tat structure.

    Corriger tous les malloc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    polynome p1 = malloc(sizeof(polynome));
    comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    polynome p1 = malloc(sizeof(* polynome));
    En fait, j'ai l'impression que le problème est plus profond que cela et cette écriture me perturbe. Dans ton nommage de variables ou de type, tu ne fais pas de différence entre objet et pointeur sur objet et cela induit ce genre d'erreur d'inattention.

    Pour ma part, je ne définis jamais de type pointeur (sauf les pointeurs de fonctions), je préfère mettre la notion de pointeur (le caractère *) dans le code comme cela on vois bien si c'est un objet plein ou un pointeur. Cela donnerait un truc comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef struct monome {
    	float coeff;
    	float degre;
    	struct monome *suiv;
    } monome, polynome;
    ...
    polynome *p1 = malloc(sizeof(* polynome));
    if(p1 == NULL)
    {
       ...
    }
    Bien sûr, il y aurait d'autre modifications à faire car dans ce cas, monome et polynome sont identiques donc l'un des deux est superflu. D'ailleurs est ce que le membre suivant a un sens pour un monome ?

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2009
    Messages : 389
    Points : 192
    Points
    192
    Par défaut
    J'ai corrigé mes malloc, et ajouté quelques modifications à mon code :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    polynome additionner(polynome p1, polynome p2) {
    	polynome tmp = (polynome) malloc(sizeof(polynome));
    	polynome premier = (polynome) malloc(sizeof(polynome));
     
    	polynome po1 = (polynome) malloc(sizeof(polynome));
    	po1 = p1;
    	polynome po2 = (polynome) malloc(sizeof(polynome));
    	po2 = p2;
     
    	if (po1->degre > po2->degre) {
    		premier = insererEnTete(NULL,p1->coeff, p1->degre);
    		po1 = po1->suiv;
    	} else if (po1->degre < po2->degre) {
    		premier = insererEnTete(NULL,po2->coeff, po2->degre);
    		po2 = po2->suiv;
    	} else {
    		premier = insererEnTete(NULL,po1->coeff + po2->coeff, po1->degre + po2->degre);
    		po1 = po1->suiv;
    		po2 = po2->suiv;
    	}
    	tmp = premier;
     
    	while ((po1->coeff != 0) && (po2->coeff != 0)) {
     
    		if (po1->degre > po2->degre) {
    			insererEnQueue (tmp,po1->coeff, po1->degre);
    			po1 = po1->suiv;
    		} else if (po2->degre > po1->degre) {
    			insererEnQueue (tmp,po2->coeff, po2->degre);
    			po2 = po2->suiv;
    		} else if (po1->degre == po2->degre) {
    			insererEnQueue (tmp,po1->coeff + po2->coeff, p2->degre);
    			po1 = po1->suiv;
    			po2 = po2->suiv;
    		}
     
    		if (po1 == NULL) {
    			po1 = insererEnQueue (po1,0,0);
    		}
    		if (po2 == NULL) {
    			po2 = insererEnQueue (po2,0,0);
    		}
    	}
    	return premier;
    }

    Ca fonctionne presque, mais le monôme le plus faible n'est pas pris en compte.

    D'où vient le problème?

    Concernant l'allocation de mes polynômes, est-ce que je le fais correctement? J'ai fait
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    polynome tmp = (polynome) malloc(sizeof(polynome));
    au lieu de
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    polynome p1 = malloc(sizeof(* polynome));

    Merci.

  7. #7
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Concernant l'allocation de mes polynômes, est-ce que je le fais correctement? J'ai fait

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    polynome tmp = (polynome) malloc(sizeof(polynome));
    C'est incorrect. polynome est un pointeur, sizeof(polynome) donne la taille d'un pointeur.

    Tu peux écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    polynome tmp = malloc(sizeof *tmp);
    Ceci mis à part, il y a des incohérences dans ton code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	polynome po1 = (polynome) malloc(sizeof(polynome));
    	po1 = p1;
    A quoi sert de faire l'allocation puisqu'à la ligne suivante tu écrases l'adresse obtenue avec le malloc par la valeur de p1 ?
    L'effet obtenu est une fuite mémoire.

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2009
    Messages : 389
    Points : 192
    Points
    192
    Par défaut
    Bonjour, merci.
    Pourtant je ne comprends pas, mon code fonctionne parfaitement, maintenant que j'ai corrigé cette erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    else if (po1->degre == po2->degre) {
    			insererEnQueue (tmp,po1->coeff + po2->coeff, po2->degre);
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    else if (po1->degre == po2->degre) {
    			insererEnQueue (tmp,po1->coeff + po2->coeff, p2->degre);
    (petite erreur d'inattention).

    Donc, si je suis vos conseils, pas besoin d'allocation mémoire ici? Ni dans ma fonction d'addition, ni dans mon main?


Discussions similaires

  1. Problème d'allocation mémoire
    Par Fibus dans le forum GTK+ avec C & C++
    Réponses: 6
    Dernier message: 10/01/2008, 17h35
  2. Problème d'allocation mémoire
    Par elmayor1983 dans le forum C++
    Réponses: 5
    Dernier message: 14/02/2007, 11h08
  3. Problème d'allocation mémoire et fork
    Par Conap dans le forum Langage
    Réponses: 3
    Dernier message: 20/07/2006, 16h34
  4. Problème d'allocation mémoire
    Par araya dans le forum C
    Réponses: 2
    Dernier message: 04/05/2006, 21h03
  5. Problème d'allocation mémoire
    Par cali1983 dans le forum C++
    Réponses: 10
    Dernier message: 11/03/2006, 00h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo