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 :

Valgrind est génial ! et petit pb de libération mémoire


Sujet :

C

  1. #1
    Membre habitué
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Points : 144
    Points
    144
    Par défaut Valgrind est génial ! et petit pb de libération mémoire
    C'est juste pour que tout le monde le sache. ;-)
    J'ai rarement utilisé un outil aussi bien conçu. Clair, pratique, léger... tout ça! Malgré la masse, je veux l'avalanche d'options, tout va bien parce les valeurs standard font juste ce qu'on veut dans le cas courant.
    Enfin, je n'ai pour l'instant utilisé que l'outil memcheck. C'est outil m'a fait comprendre et prendre conscience de ce à quoi il faut faire attention dans la gestion de mémoire. C'est bien mieux que ce que j'attendais. Et à l'occasion de cette chasse aux fuites, j'ai aussi trouvé un vrai bug logique ; que j'aurais eu du mal à diagnostiquer d'ailleurs, même si j'avais la chance qu'il se manifeste clairement.

    J'espère que les outils de profiling sont aussi bien foutus.

    A part ça, 3 petites questions relatives à la mémoire:

    1. Comment libérer une valeur de retour directement utilisée; typiquement une chaîne. Exemple.
    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
     char * chaine (size_t count, Data data) {
       char * s = malloc (count * sizeof(char)) ;
       // .........mets des choses dedans............
       return s ;
    }
     
    // version 1
    void affiche_chaine () {
       // .........prépare les donées............
     
       // affiche les données
       // *** fuite de mémoire ***
       printf ("voilà : %s", chaine (size_t count, Data data) ;
    }
     
    // version 2
    void affiche_chaine () {
       // .........prépare les donées............
     
       // affiche les données
       // *** fuite de légèreté ***
       char * s  = chaine (size_t count, Data data) ;
       printf ("voilà : %s", s) ;
       free (s) ;
    }
    Bon, vous avez ma solution actuelle en version 2. Je ne pige pas bien pourquoi comment je me trouve obligé d'écrire un code si lourdingue.
    EDIT: En fait, le point clé, c'est qu'il faut nécessairement nommer ce qu'on veut/doit libérer, non?

    2. Si j'écris une func qui retourne une chaîne, comme ci-dessus, mais en l'allouant sur le pile (explicitement ou non), la fonction appelante la reçoit quand même! (alors que bien sûr je ne passe en retour en fait qu'un pointeur). Comment ça se fait?
    Ca voudrait dire qu'il y a une copie implicite de la zone pointée par la valeur de retour (comme si c'était cette zone la vlaeur de retour), ou alors que le compilo ne libère pas cette zone, "sachant" qu'elle est utilisée ailleurs. ??? J'ai jamais entendu parler d'un truc comme (en C). Par exemple un truc comme ça marche:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char * str () { return (char *) "xyz" ;}
    int main (void) { puts (str()) ; return 0 ;}
    Y a un fantôme dans mon compilo? Qu'est-ce que je n'ai pas pigé?

    J'ai oublié quel était mon problème n° 3 !

    Denis

  2. #2
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    +1 pour valgrind

    Pourquoi trouves-tu lourd le fait de devoir utiliser free ? C'est ainsi que les choses vont ...
    Sinon si tu veux tu peux utiliser l'attribut de variable cleanup qui est une extension gcc.
    cleanup (cleanup_function)
    The cleanup attribute runs a function when the variable goes out of scope. This attribute can only be applied to auto function scope variables; it may not be applied to parameters or variables with static storage duration. The function must take one parameter, a pointer to a type compatible with the variable. The return value of the function (if any) is ignored.
    If -fexceptions is enabled, then cleanup_function will be run during the stack unwinding that happens during the processing of the exception. Note that the cleanup attribute does not allow the exception to be caught, only to perform an action. It is undefined what happens if cleanup_function does not return normally.
    cf http://gcc.gnu.org/onlinedocs/gcc/Va...ttributes.html

    Cela te lie fortement à gcc ...


    2. Ta chaîne "xyz" n'est allouée ni sur la pile ni sur le tas, mais dans un data segment du programme (qui est en read only) et qui sera chargé par le loader en mémoire.

  3. #3
    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
    Si j'écris une func qui retourne une chaîne,...
    C'est un abus de langage : une fonction ne peut jamais retourner une chaine ou un tableau quelconque. Elle retourne, dans ton exemple, l'adresse du premier élément. Il n'y a pas de duplication de la chaine. Ainsi, ce code est faux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char * fonc(void)
    {
      char tab[] = "xyz";
      return tab;           // code faux
    }
    mais celui-ci est correct
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char * fonc(void)
    {
      char * tab = "xyz";
      return tab;
    }

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 483
    Points : 13 685
    Points
    13 685
    Billets dans le blog
    1
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char * fonc(void)
    {
      char * tab = "xyz";
      return tab;
    }
    Si ce code est correct, c'est bien parce que la chaîne est constante et que donc le pointeur vers cette chaîne est déterminé à la compilation et ne change pas au cours de l'exécution ?


    Ce thread vient de me décider à installer valgrind dans ma VM Debian, et j'ai fait un premier test :

    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
    #include <stdio.h>
    #include <stdlib.h>
     
    int * allouer(size_t taille)
    {
        return malloc( taille * sizeof(int) );
    }
     
    int main(void)
    {
        puts("Debut");
     
        int * tableau = allouer(100);
        int i=0;
        for(i=0; i<101; i++)
        {
            tableau[i] = i;
        }
        tableau[200] = 0;
        //free(tableau);
        puts("Fin");
        return 0;
    }
    Il me détecte bien les 3 erreurs, malin ! Je crois que je vais l'utiliser tout le temps maintenant !

  5. #5
    Membre habitué
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Points : 144
    Points
    144
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char * fonc(void)
    {
      char * tab = "xyz";
      return tab;
    }
    Si ce code est correct, c'est bien parce que la chaîne est constante et que donc le pointeur vers cette chaîne est déterminé à la compilation et ne change pas au cours de l'exécution ?


    Ce thread vient de me décider à installer valgrind dans ma VM Debian, et j'ai fait un premier test :

    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
    #include <stdio.h>
    #include <stdlib.h>
     
    int * allouer(size_t taille)
    {
        return malloc( taille * sizeof(int) );
    }
     
    int main(void)
    {
        puts("Debut");
     
        int * tableau = allouer(100);
        int i=0;
        for(i=0; i<101; i++)
        {
            tableau[i] = i;
        }
        tableau[200] = 0;
        //free(tableau);
        puts("Fin");
        return 0;
    }
    Il me détecte bien les 3 erreurs, malin ! Je crois que je vais l'utiliser tout le temps maintenant !
    Pour memcheck, ça c'est du gâteau !

    Denis

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Les chaînes littérales sont placées en mémoire statique (en mémoire statique constante sous les OS modernes, d'ailleurs).
    À l'inverse, ceci ne marcherait pas parce qu'il réserve un buffer dans la pile:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char * fonc(void)
    {
      char tab[] = "xyz";
      return tab; /*mauvais*/
    }

  7. #7
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 483
    Points : 13 685
    Points
    13 685
    Billets dans le blog
    1
    Par défaut
    Une fois dit ça parait tellement normal... Merci

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

Discussions similaires

  1. Réponses: 41
    Dernier message: 01/10/2013, 19h20
  2. [Humour] Windows ? C'est génial !
    Par Bovino dans le forum La taverne du Club : Humour et divers
    Réponses: 41
    Dernier message: 23/09/2008, 10h09
  3. Réponses: 2
    Dernier message: 07/12/2006, 19h03
  4. [COM] Libération mémoire
    Par MC2 dans le forum Bibliothèques et frameworks
    Réponses: 5
    Dernier message: 13/01/2006, 16h15
  5. FIREBIRD + APPLI EN C : Problèmes de libération mémoire
    Par lio33 dans le forum Connexion aux bases de données
    Réponses: 4
    Dernier message: 16/09/2005, 09h07

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