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 :

Erreur de mémoire


Sujet :

C

  1. #1
    Membre expérimenté
    Inscrit en
    Décembre 2009
    Messages
    282
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 282
    Par défaut Erreur de mémoire
    bonjour tout le monde,

    j'ai une calculatrice à faire avec lex/yacc, pas très dur en soi mais j'ai un gros problème de C que je ne comprend pas. Ca porte sur la mémoire comme d'habitude, je ne comprends pas pourquoi j'ai une erreur de segmentation, je vous montre :

    mes déclarations :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
       #include<unistd.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
     
    	typedef struct symb {
    		char* nom;
    		double val;
    		struct symb* suiv;
    	} symb;
    et ma fonction
    Code : 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
     
    symb* affecter_variable(symb* table,char* nom, double val) {
    	symb* q;
     
    	q = (symb*) malloc (sizeof(struct symb));
     
    	printf("%s : nouveau mot\n",nom);
    	q->nom = (char*) malloc (sizeof(char) * (strlen(nom)+1));
    	printf("malloc mot réussi\n");
     
    	strcpy(q->nom,nom);
     
    	q->val = val;
    	q->suiv = table;
    	table = q;
     
            return table;
    }
    Ce que je ne comprends pas c'est que cette fonction réussi 2 fois, et à la troisième me met une erreur de segmentation à cet endroit là "q->nom = (char*) malloc (sizeof(char) * (strlen(nom)+1));", car il affiche le premier printf mais pas le deuxième. Pourtant q a bien été alloué à la ligne précédente !!

    J'ai essayé de le lancer avec le logiciel VALGRIND (logiciel de détection d'erreur mémoire), il me dit dès le premier mot qu'il y a une erreur de mémoire quand il fait strcpy (je copie colle l'erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    ==4429== Use of uninitialised value of size 4
    ==4429==    at 0x4025C2B: strcpy (mc_replace_strmem.c:303)
    ==4429==    by 0x804927E: yylex (in /home/ticroch2/Bureau/projet/a.out)
    ==4429==    by 0x8048B57: yyparse (in /home/ticroch2/Bureau/projet/a.out)
    ==4429==    by 0x804A8F1: main (in /home/ticroch2/Bureau/projet/a.out)
    ==4429== 
    ==4429== Invalid write of size 1
    ==4429==    at 0x4025C2B: strcpy (mc_replace_strmem.c:303)
    ==4429==    by 0x804927E: yylex (in /home/ticroch2/Bureau/projet/a.out)
    ==4429==    by 0x8048B57: yyparse (in /home/ticroch2/Bureau/projet/a.out)
    ==4429==    by 0x804A8F1: main (in /home/ticroch2/Bureau/projet/a.out)
    ==4429==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
    Voilà je crois que je n'ai rien oubié dans ce post, si quelqu'un à une idée d'où ça peut venir ça m'intéresse !!

    Merci d'avance

  2. #2
    Membre émérite
    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
    Par défaut
    Ton code m'a l'air correct.
    Sauf que ... tu as une erreur ici je suppose :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    q->suiv = table;
    table = q;
    Si je suis ces 2 lignes tu fais pointer q->suiv sur table, et ensuite table = q. Donc table == table-suiv

  3. #3
    Membre expérimenté
    Inscrit en
    Décembre 2009
    Messages
    282
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 282
    Par défaut
    Je pourrais faire direct un return q en oubliant la ligne table = q je pense, mais d'après le petit dessin que j'ai fait pour vérifier ce n'est pas faux tout de même :

    On place table à la suite de q
    On donne comme valeur à table la valeur de Q
    Donc table possède bien au début q, et ensuite l'ancien table, je n'ai donc fait qu'une insertion en tête !!

  4. #4
    Membre expérimenté
    Inscrit en
    Décembre 2009
    Messages
    282
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 282
    Par défaut
    ah oui aussi, j'obtient deux erreurs différentes : celle citée au dessus, une simple erreur de segmentation, et parfois je reçois aussi ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    a.out: malloc.c*:3074*:*sYSMALLOc:  L'assertion «*(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)*» a échoué.

  5. #5
    Membre émérite
    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
    Par défaut
    Testes les retours de tes mallocs

    Et je maintient ce que j'ai dit, tu fais pointer q sur lui-même.

  6. #6
    Membre expérimenté
    Inscrit en
    Décembre 2009
    Messages
    282
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 282
    Par défaut
    J'ai ajouté, en testant si c'est NULL. A aucun moment malloc me renvoi NULL, malgré l'erreur de segmentation

    Code : 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
     
    symb* affecter_table(symb* table,char* nom, double val) {
    	symb* q;
     
    	q = (symb*) malloc (sizeof(struct symb));
    	if (q == NULL) {
    		printf("ALLOCATION NULLE\n");
    	}
     
    	printf("%s : nouveau mot\n",nom);
    	q->nom = (char*) malloc (sizeof(char) * (strlen(nom)+1));
    	if (q->nom == NULL) {
    		printf("ALLOCATION MOT NULLE\n");
    	}
    	printf("malloc mot réussi\n");
    	strcpy(q->nom,nom);
     
    	q->val = val;
    	q->suiv = table;
    	return q;
    }

  7. #7
    Membre émérite
    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
    Par défaut
    Ta fonction est correcte, tu pourrais nous montrer le reste du code ?

  8. #8
    Membre expérimenté
    Inscrit en
    Décembre 2009
    Messages
    282
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 282
    Par défaut
    ouais mais bon c'est long, et après c'est pas vraiment du C, c'est faut avec Yacc et Lex.

    je te montre les règles du fichier yacc qui l'appelle :

    Code : 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
     
    %{
       #include<unistd.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
     
    	typedef struct symb {
    		char* nom;
    		double val;
    		struct symb* suiv;
    	} symb;
     
    	symb* table;
     
    	symb* affecter_table(symb* table,char* nom, double val);
    	double valeur_table(symb* table,char* nom);
    %}
    %union {
    	double val;
    	symb* ptr;
    }
    %token <val> NOMBRE
    %token <ptr> NOM
    %type <val> expr;
    %left '+' '-'
    %left '*' '/'
    %right MOINSU
    %right AFFECT
    %%
     
    ligne: ligne expr '\n' {printf("res: %f\n",$2);}
            | ligne '\n'
            | 
    	;
     
    expr: expr '+' expr {$$ = $1 + $3;}
    	| expr '-' expr {$$ = $1 - $3;}
    	| expr '*' expr {$$ = $1 * $3;}
    	| expr '/' expr { if ($3 == 0) { yyerror("division par 0\n");
    					YYERROR;
    					}
    			$$ = ($1 / $3);
    			}
    	| '(' expr ')' {$$ = ($2);}
    	| '-' expr %prec MOINSU {$$ = - $2;}
    	| NOMBRE 
    	| NOM '=' expr %prec AFFECT {table=affecter_table(table,$1->nom,$3);$$ = $3;}
    	| NOM {$$ = valeur_table(table,$1->nom);}
    	; 
    %%
     
    #include "lex.yy.c"
    l'erreur se situe dans les dernières ligne, à cet endroit là "| NOM '=' expr %prec AFFECT {table=affecter_table(table,$1->nom,$3);$$ = $3;}"

  9. #9
    Membre expérimenté
    Inscrit en
    Décembre 2009
    Messages
    282
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 282
    Par défaut
    c'est bon j'ai trouvé mon problème, ma variable nom qui était mal initialisé (ce qui faisait que des fois ça marche, d'autre non, les joies du C :p)

    par contre pouet_forever, je te maintiens que mon code est bien une insertion en tête avec des pointeurs, j'ai fait un petit programme vite fait pour te montrer que ça marchait bien :

    Code : 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
     
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef struct liste {
    	int val;
    	struct liste* suiv;
    } liste;
     
    int main(int argc, char** argv) {
    	liste* l;
    	liste* q;
    	int nb;
    	int n = argc;
    	l= NULL;
    	for (n = 1; n < argc-1; n++)  {
    		nb = atoi(argv[n]);
    		printf("On insere en tete le %d\n",nb);
     
    		/*creation du nouvel element*/
    		q = (liste*) malloc (sizeof(struct liste));
    		q->val = nb;
    		/*insertion en début de liste*/
    		q->suiv = l;
    		l = q;
     
    		/*description de la liste*/
     
    		q=l;
    		while (q != NULL) {
    			printf("%d ",q->val);
    			q = q->suiv;
    		}
    		printf("\n");
    	}
    }
    test ça, et passe des nombres en arguments, tu verra que ça fais bien une insertion en tête avec les instructions "q->suiv = l; l = q;"

    sur ce, merci de tes réponses quand même !!!

  10. #10
    Membre émérite
    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
    Par défaut
    Après réflexion tu as raison
    Sauf que (bah oui hein :p ) en général quand on ajoute un élément dans une liste chaînée on ne le fait pas dans la fonction, on renvoie un pointeur sur cet élément
    Pour Yacc et Lex je ne connais pas j'ai pas pu t'aider désolé

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. erreur de mémoire
    Par dybmans dans le forum Linux
    Réponses: 8
    Dernier message: 13/01/2010, 17h08
  2. [PR-2007] Demarrage Project 2007 : "erreur de mémoire"
    Par Invité dans le forum Project
    Réponses: 15
    Dernier message: 28/05/2009, 08h16
  3. [Upload] Erreur de mémoire lors d'un upload
    Par alpking dans le forum Langage
    Réponses: 3
    Dernier message: 10/11/2006, 10h35
  4. Erreur Allocation mémoire
    Par Thordax dans le forum C++
    Réponses: 10
    Dernier message: 05/04/2006, 21h29
  5. Programme détectant les erreurs de mémoire
    Par gids01 dans le forum MFC
    Réponses: 2
    Dernier message: 07/12/2005, 10h57

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