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

GTK+ avec C & C++ Discussion :

Détection de fuites mémoire avec Valgrind


Sujet :

GTK+ avec C & C++

  1. #21
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 7
    Points : 8
    Points
    8
    Par défaut
    Si si, j'ai compilé avec l'option -g et j'ai une "Erreur de segmentation (core dumped)".
    Tu avais raison, les erreurs étaient cachées dans le rapport. Je me demande seulement, pourquoi elles ne figuraient pas dans le resumé.

    Voilà ce que je veux faire :

    1 - Aller chercher dans un fichier une ligne par exemple : "etat1 etat2 etat3 e4 e5#" (espaces compris)

    2 - Maintenant, je voudrais créer un tableau de 5 pointeurs. Chaque pointeur, pointera sur chacune des chaines de caractères. Autrement dit, si on appelle, le tableau : tab_pointeurs, on aura :

    tab_pointeurs[0] qui pointe sur "etat1"
    tab_pointeurs[1] qui pointe sur "etat2"
    ......
    tab_pointeurs[4] qui pointe sur "e5"

    SEULEMENT, on ne sait pas à l'avance combien d'états on aura dans le fichier, et donc de combien de pointeurs on aura besoin. Et on ne sait pas non plus quelle taille feront chaque chaine de caractères. D'où les allocations mémoires.

    Je ne sais pas si le problème est assez clair .

    Voila le rapport valgrind :
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    Les etats sont : 
    ==16030== Invalid read of size 1
    ==16030==    at 0x4022493: strlen (mc_replace_strmem.c:246)
    ==16030==    by 0x40879C4: puts (in /lib/tls/i686/cmov/libc-2.5.so)
    ==16030==    by 0x80489F6: rechercher_etats (machine_wikipedia.c:145)
    ==16030==    by 0x80490A6: main (machine_wikipedia.c:467)
    ==16030==  Address 0x41711BA is 0 bytes after a block of size 2 alloc'd
    ==16030==    at 0x4021620: malloc (vg_replace_malloc.c:149)
    ==16030==    by 0x804891C: rechercher_etats (machine_wikipedia.c:126)
    ==16030==    by 0x80490A6: main (machine_wikipedia.c:467)
    e1
    e2
    e3
    e4
    e5
     
    ==16030== 
    ==16030== Invalid read of size 4
    ==16030==    at 0x80490B8: main (machine_wikipedia.c:476)
    ==16030==  Address 0xBEE5C5A0 is just below the stack ptr.  To suppress, use: --workaround-gcc296-bugs=yes
    ==16030== 
    ==16030== Invalid read of size 1
    ==16030==    at 0x4022493: strlen (mc_replace_strmem.c:246)
    ==16030==    by 0x406F0CA: vfprintf (in /lib/tls/i686/cmov/libc-2.5.so)
    ==16030==    by 0x4074652: printf (in /lib/tls/i686/cmov/libc-2.5.so)
    ==16030==    by 0x80490C9: main (machine_wikipedia.c:476)
    ==16030==  Address 0x41711BA is 0 bytes after a block of size 2 alloc'd
    ==16030==    at 0x4021620: malloc (vg_replace_malloc.c:149)
    ==16030==    by 0x804891C: rechercher_etats (machine_wikipedia.c:126)
    ==16030==    by 0x80490A6: main (machine_wikipedia.c:467)
    Avant : tableau_etats[0] = e1
    Entrez le nom du fichier 'DONNEES' (chemin complet, du style c:/Documents/.../fichiertexte.txt)
    ==16030== 
    ==16030== Invalid read of size 4
    ==16030==    at 0x80490D9: main (machine_wikipedia.c:480)
    ==16030==  Address 0xBEE5C5A0 is just below the stack ptr.  To suppress, use: --workaround-gcc296-bugs=yes
    ==16030== 
    ==16030== Invalid read of size 1
    ==16030==    at 0x4022488: strlen (mc_replace_strmem.c:246)
    ==16030==    by 0x406F0CA: vfprintf (in /lib/tls/i686/cmov/libc-2.5.so)
    ==16030==    by 0x4074652: printf (in /lib/tls/i686/cmov/libc-2.5.so)
    ==16030==    by 0x80490EA: main (machine_wikipedia.c:480)
    ==16030==  Address 0x60 is not stack'd, malloc'd or (recently) free'd
    ==16030== 
    ==16030== Process terminating with default action of signal 11 (SIGSEGV)
    ==16030==  Access not within mapped region at address 0x60
    ==16030==    at 0x4022488: strlen (mc_replace_strmem.c:246)
    ==16030==    by 0x406F0CA: vfprintf (in /lib/tls/i686/cmov/libc-2.5.so)
    ==16030==    by 0x4074652: printf (in /lib/tls/i686/cmov/libc-2.5.so)
    ==16030==    by 0x80490EA: main (machine_wikipedia.c:480)
    Apres : tableau_etats[0] = ==16030== 
    ==16030== ERROR SUMMARY: 9 errors from 5 contexts (suppressed: 11 from 1)
    ==16030== malloc/free: in use at exit: 10 bytes in 5 blocks.
    ==16030== malloc/free: 6 allocs, 1 frees, 362 bytes allocated.
    ==16030== For counts of detected errors, rerun with: -v
    ==16030== searching for pointers to 5 not-freed blocks.
    ==16030== checked 64,088 bytes.
    ==16030== 
    ==16030== LEAK SUMMARY:
    ==16030==    definitely lost: 10 bytes in 5 blocks.
    ==16030==      possibly lost: 0 bytes in 0 blocks.
    ==16030==    still reachable: 0 bytes in 0 blocks.
    ==16030==         suppressed: 0 bytes in 0 blocks.
    ==16030== Use --leak-check=full to see details of leaked memory.
    Erreur de segmentation (core dumped)
    Je ne vois toujours pas où sont mes erreurs. Voici les lignes concernées :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ligne 126 : tab_etat[j] = malloc(sizeof(char)*taille_nom_etat);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                 printf("Les etats sont : \n");
                 for(j=0;j<maxetats;j++){
    ligne 145 :   ---->  printf("%s\n",tab_etat[j]);  
                 }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ligne 467 : tableau_etats = rechercher_etats(p_fichierM);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ligne 476 : printf("tableau_etats[0] = %s\n",tableau_etats[0]);
    Merci d'avance

  2. #22
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Points : 1 633
    Points
    1 633
    Par défaut
    Le code que tu donnes est très fragmenté, c'est dur de dire ce qui ne va pas à partir de ça. Tout ce que je peux te dire, c'est que valgrind t'indique qu'à la ligne 145 de ton programme, tu fais un accés mémoire invalide (ce qui entraîne peut être le plantage de ton programme). La 2ème partie du rapport semble indiquer que tu n'as pas alloué suffisamment de mémoire à la ligne 126 pour une chaîne de caractère. g_strdup ou g_strdup_printf te seraient peut être utiles ?

  3. #23
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 7
    Points : 8
    Points
    8
    Par défaut
    Ok. Pour plus de clarté, voici la portion entière du code :

    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
    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
     
    typedef char* t_etats;
    'etats' est une variable globale. Un tableau de 500 caractères maxi qui contiendra toute la ligne du fichier (espaces compris).
    i est la variable qui permet de se déplacer dans ce tableau.
     
    //////////////////////////////////////// FONCTION RECHERCHER_ETATS ///////////////////////////////////////////////
    /*  
     * Recherche les états de la machine dans le fichier 'machine'.
     * Préconditions : Le fichier existe
     * Postconditions : Renvoie un tableau de chaîne de caractères (les états).
    */
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    t_etats* rechercher_etats(FILE* fichier){
     
        char marqueur = '$'; t_etats* etats_ret=NULL;
     
        /* Parcours du fichier ligne par ligne. On sort de la boucle une fois le mot trouvé.*/
        while (!feof(fichier)){
     
              fgets(etats,sizeof(etats),fichier);           
              if(etats[0] != marqueur){
                    break;  
              }  
        }
        printf("Etats recherches : %s",etats);
        printf("Taille : %d\n",strlen(etats)-2); // on enlève le '#' et le marqueur de fin '\0'
        int unsigned i=0; int j=0; int unsigned k=0; int maxetats=0; int taille_nom_etat=0; int t=0;
     
        // On compte le nombre total d'états présents pour la machine. En comptant le nombre d'espace entre leurs noms et en ajoutant 1.
        while(k<strlen(etats)-2){
           if(etats[k]==' '){  
              maxetats++;  
           }
           k++;
        }
        maxetats++;
        printf("nbre d'etats : %d\n",maxetats);
     
        /* tab_etat est un tableau de pointeurs. Sa taille (maxetats) n'est pas connue à l'avance. Mais, on en aura besoin un peu plus haut
         * dans la fonction "indice_etat". Sa taille réelle est contenue dans la variable maxetats et on ajoute une case de plus qui
         * contiendra toujours NULL. Cette case jouera le rôle de marqueur de fin et nous permettra à l'aide d'une boucle de déterminer la
         * taille du tableau. Les indices vont de 0 à maxetats-1. Donc, si on ajoute une colonne de plus, elle aura pour indice 'maxetats'.
         */
        t_etats tab_etat[maxetats+1]; tab_etat[maxetats]=NULL;
     
        for(j=0;j<maxetats;j++){
     
    	  /* On compte la taille en caracteres de chaque etat.
    	   * strlen(mot)-2 pour éviter de prendre le dernier caractère de la chaine # et le marqueur de fin : '\0'.
    	   */                     
    	   while(etats[i]!=' ' && i<strlen(etats)-2){
    	         i++;              
                   taille_nom_etat++;                                                                     
    	    }
    	    printf("taille du nom de l'etat = %d\n",taille_nom_etat);
    	    //size_t n = taille_nom_etat;
    	    /*
    	     * Pour chaque état, on alloue une zone mémoire de taille variable qui contiendra son nom (chaine de caractère qui le
    	     * représente). Ceci, en partant du principe que les noms (des états) i.e les chaines de caractère sont de tailles différentes.
    	     *
    	     * Si  par exemple, nous avons les états : 'etat1' 'etat2', 'e3', 'q4', 'eta5'
    	     * On allouera :
    	     * Une zone mémoire de 5 caractères pour chacun des états 1 et 2. 
    	     * Une zone de 2 caractères pour chacun des états 3 et 4 et
                * Une zone de 4 caractères pour l'état 5.
    	     * tab_etat est un tableau de pointeurs sur ces caractères. Donc,
    	     * tab_etat[0] pointera sur l'état 1 et donc sur la chaîne : 'etat1'
    	     * tab_etat[1] pointera sur l'état 2 et donc sur la chaîne : 'etat2'
    	     * tab_etat[2] pointera sur l'état 3 et donc sur la chaîne : 'e2'
    	     * tab_etat[3] pointera sur l'état 4 et donc sur la chaîne : 'q4'
    	     * tab_etat[4] pointera sur l'état 5 et donc sur la chaîne : 'eta5'
    	     */
    	     tab_etat[j] = malloc(sizeof(char)*taille_nom_etat);
    	     if(tab_etat[j]==NULL){
    	         printf("\n Allocation Impossible \n");
    	         exit(EXIT_FAILURE);
    	     }
    	     //printf("i = %d\n",i);
    	     int temp; temp = taille_nom_etat; int taille; taille = strlen(etats)-2;
    	     if(i <= taille){
    	          for(t=0;t<taille_nom_etat;t++){
    	               tab_etat[j][t]=etats[i-temp];
    	               temp--;
    	          }
    	      }
    	      i++;
    	      taille_nom_etat=0;              
         }               
     
         printf("Les etats sont : \n");
         for(j=0;j<maxetats;j++){
              printf("%s\n",tab_etat[j]);  
         }
         //system("PAUSE");
         printf("\n");
         etats_ret = tab_etat;
         return etats_ret;
    }
    // Fin de la fonction rechercher_etats
    Cette fonction me retourne le tableau de pointeurs (cf post précédent) où chaque pointeur pointera sur les chaine de caractères.

    Edit : J'ai précisé le numéro des lignes dans mon post précédent.

  4. #24
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Points : 1 633
    Points
    1 633
    Par défaut
    J'ai l'impression que tu recopies des caractères dans des tableaux sans jamais mettre de \0 terminal, si c'est le cas, ça n'est pas étonnant que printf n'aime pas ça.

  5. #25
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 7
    Points : 8
    Points
    8
    Par défaut
    Effectivement, je ne remet plus le caractère terminal. Je corrige ça et je te dis si ça marche .

    Edit : le nombre d'erreurs a surement diminué. Mais l' "Erreur de segmentation (core dumped)" persiste . Je n'arrive pas à comprendre/interpréter les messages de valgrind...

    Nouveau rapport valgrind :
    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
     
    ==13925== Invalid read of size 4
    ==13925==    at 0x80490CD: main (machine_wikipedia.c:477)
    ==13925==  Address 0xBEC565A0 is just below the stack ptr.  To suppress, use: --workaround-gcc296-bugs=yes
    Avant : tableau_etats[0] = e1
    Entrez le nom du fichier 'DONNEES' (chemin complet, du style c:/Documents/.../fichiertexte.txt)
    ==13925== 
    ==13925== Invalid read of size 4
    ==13925==    at 0x80490EE: main (machine_wikipedia.c:481)
    ==13925==  Address 0xBEC565A0 is just below the stack ptr.  To suppress, use: --workaround-gcc296-bugs=yes
    ==13925== 
    ==13925== Invalid read of size 1
    ==13925==    at 0x4022488: strlen (mc_replace_strmem.c:246)
    ==13925==    by 0x406F0CA: vfprintf (in /lib/tls/i686/cmov/libc-2.5.so)
    ==13925==    by 0x4074652: printf (in /lib/tls/i686/cmov/libc-2.5.so)
    ==13925==    by 0x80490FF: main (machine_wikipedia.c:481)
    ==13925==  Address 0x60 is not stack'd, malloc'd or (recently) free'd
    ==13925== 
    ==13925== Process terminating with default action of signal 11 (SIGSEGV)
    ==13925==  Access not within mapped region at address 0x60
    ==13925==    at 0x4022488: strlen (mc_replace_strmem.c:246)
    ==13925==    by 0x406F0CA: vfprintf (in /lib/tls/i686/cmov/libc-2.5.so)
    ==13925==    by 0x4074652: printf (in /lib/tls/i686/cmov/libc-2.5.so)
    ==13925==    by 0x80490FF: main (machine_wikipedia.c:481)
    Apres : tableau_etats[0] = ==13925== 
    ==13925== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 11 from 1)
    ==13925== malloc/free: in use at exit: 15 bytes in 5 blocks.
    ==13925== malloc/free: 6 allocs, 1 frees, 367 bytes allocated.
    ==13925== For counts of detected errors, rerun with: -v
    ==13925== searching for pointers to 5 not-freed blocks.
    ==13925== checked 64,088 bytes.
    ==13925== 
    ==13925== LEAK SUMMARY:
    ==13925==    definitely lost: 15 bytes in 5 blocks.
    ==13925==      possibly lost: 0 bytes in 0 blocks.
    ==13925==    still reachable: 0 bytes in 0 blocks.
    ==13925==         suppressed: 0 bytes in 0 blocks.
    ==13925== Use --leak-check=full to see details of leaked memory.
    Erreur de segmentation (core dumped)
    AR

  6. #26
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    340
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 340
    Points : 177
    Points
    177
    Par défaut
    pour les segmentation fault, gdb te donnera plus d'info que valgrind.
    L'Opus attire les Prélats

Discussions similaires

  1. Fuites mémoire avec valgrind sur un exemple simple
    Par Kazujoshi dans le forum GTK+ avec C & C++
    Réponses: 5
    Dernier message: 03/11/2010, 01h56
  2. Fuite mémoire avec code externe
    Par samW7 dans le forum C++
    Réponses: 8
    Dernier message: 01/02/2008, 02h33
  3. [AJAX] Appolo 13 - Fuite mémoire avec XHR
    Par mecatroid dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 24/09/2007, 14h52
  4. Fuites mémoires avec Vector
    Par ..alex.. dans le forum SL & STL
    Réponses: 15
    Dernier message: 10/08/2006, 11h35
  5. Fuite mémoire avec valgrind
    Par franchouze dans le forum C++
    Réponses: 3
    Dernier message: 05/06/2006, 16h47

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