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

Langage C++ Discussion :

Malloc et Free pour une valeur de retour d'une fonction


Sujet :

Langage C++

  1. #1
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Juin 2007
    Messages
    204
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2007
    Messages : 204
    Points : 89
    Points
    89
    Par défaut Malloc et Free pour une valeur de retour d'une fonction
    Bonjour à tous,

    J'utilise dans mon projet pas mal de malloc pour allouer dynamiquement la mémoire à des char*. D'après ce que j'ai lu et ce qu'on m'a dit, pour éviter les fuites de mémoire, il faut faire un free pour chaque malloc dans le programme.

    Hors j'ai un problème pour librérer la mémoire sur les mallocs que j'ai fait sur les valeurs de retour de mes fonctions.

    Par exemple j'ai une fonction "SAStrToChar" qui va transformer une string SA (string particulière que j'utilise via une api) en char* :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    char* SAStrToChar(SAString theSAStr)
    {
    	string theString = (string)theSAStr;
    	Int32 length = theString.length()+1;
    	char* returnValue = (char *) malloc(length);
    	sprintf_s(returnValue, length, "%s", theString.c_str());
     
    	return returnValue;
    }
    Seulement voilà, j'ai essayé de créer une variable "tempReturn" sur laquelle je vais faire le malloc, puis je vais transférer son contenu dans returnValue, libérer tempReturn, et retourner returnValue : returnValue est vide, enfin rempli de caractères spéciaux comme si j'avais libérer returnValue.

    Exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    char* SAStrToChar(SAString theSAStr)
    {
    	char* returnValue = "";
    	string theString = (string)theSAStr;
    	Int32 length = theString.length()+1;
    	char* tempReturn = (char *) malloc(length);
    	sprintf_s(tempReturn, length, "%s", theString.c_str());
     
    	returnValue = tempReturn;
    	free(tempReturn);
     
    	return returnValue;
    }
    Quand je libère la mémoire de tempReturn, sa libère aussi returnValue!
    Savez-vous comment faire dans ce cas pour libérer la mémoire?

    Merci d'avance!

  2. #2
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    576
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 576
    Points : 1 528
    Points
    1 528
    Par défaut
    Salut,

    Tu peux libérer la mémoire en dehors de la 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
     
    char* toto()
    {
      return malloc(42);
    }
     
    void tata()
    {
      char* buff = toto();
      // tu fait ce que tu as à faire avec buf
      ...
     
      // libère la mémoire alloué dans toto();
      free(buff)
    }
    Malloc alloue la mémoire sur une mémoire appelé le tas. Le tas, contrairement à la mémoire de la pile, n'est pas "détruite" en sortant de la fonction.

    En C++, on évite en général d'utiliser les malloc / free (très orienté C) au profit des new / delete.

    Mais, essaye d'utiliser les std::vector (cf faq vector) au lieu de gérer ta mémoire à la main. Ca te facilitera grandement les choses.
    La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer. - Antoine de Saint-Exupéry

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Je ne maîtrise pas bien les fonctions du C, mais pourquoi n'utilises-tu pas strcpy() ?

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    J'irai plus loin en disant : et pourquoi tu te casses la tête à créer une variable ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    const char* SAStrToChar(SAString theSAStr)
    {
       string theString = (string)theSAStr;
    	return theString.c_str());
    }
    Enfin il y a fort à parier que le passage par une std::string temporaire est lui aussi inutile.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Juin 2007
    Messages
    204
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2007
    Messages : 204
    Points : 89
    Points
    89
    Par défaut
    Salut et merci pour vos réponses.

    Pyros quand tu dit qu'en C++ on utilise plutôt les new / delete, tu veux dire de cette façon?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char* la_chaine = new char[longueur_dynamique];

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    En fait, cela serait pas mal que tu nous donnes une idée du contexte d'utilisation de cette fonction, car tu n'as peut-être pas besoin de fonction...

  7. #7
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Juin 2007
    Messages
    204
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2007
    Messages : 204
    Points : 89
    Points
    89
    Par défaut
    Non mais c'était juste un exemple pour savoir comment s'y prendre quand on doit libérer la mémoire d'une valeur de retour.
    C'est à dire après avoir appelé la fonction donc je peux mettre le sujet en Résolu merci à vous

    PS: Quand à la fonction que j'ai mis en exemple je l'ai faite pour convertir des SAString (string particulière d'une API que j'utilise) en char*. En effet avec c_str() je peux convertir en const char* mais je voulais des char*.

  8. #8
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Citation Envoyé par CleeM Voir le message
    J'utilise dans mon projet pas mal de malloc pour allouer dynamiquement la mémoire à des char*. D'après ce que j'ai lu et ce qu'on m'a dit, pour éviter les fuites de mémoire, il faut faire un free pour chaque malloc dans le programme.

    Hors j'ai un problème pour librérer la mémoire sur les mallocs que j'ai fait sur les valeurs de retour de mes fonctions.
    Bonjour

    Tu mets le doigt sur l'un des problèmes importants du C et qui est corrigé dans le C++ (écrit correctement) : le problème de libration safe de la mémoire

    Tu as raison, pour chaque malloc (ou new en C++, on préfère puisqu'il lance une exception), tu dois avoir un free (un delete). Mais ce free doit être placé après avoir utilisé tes ressources allouées. Dans ton premier code, tu as la séquence d'instructions suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char* tempReturn = (char *) malloc(length); // allocation
    (...)
    free(tempReturn); // libération
    (...)
    return returnValue;
    (...) // ici tu utilises ta ressource = problème
    Comme indiqué par pyros, tu dois donc mettre le free après l'utilisation de la ressource.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char* tempReturn = (char *) malloc(length); // allocation
    (...)
    return returnValue;
    (...) // ici tu utilises ta ressource = ok
    free(tempReturn); // libération
    Le risque de fuite mémoire (ie avoir des ressources allouées qui ne sont pas libérées) est grand. L'utilisateur de la fonction ne doit pas oublier de libérer la mémoire. Si la ressources est utilisée à plusieurs endroits, il faut avoir une politique très stricte de qui gère la libération (ce que la plupart des personnes ne savent pas faire correctement). Idem si tu as beaucoup de ressources différentes allouées à gérer. Si une exception est lancée entre le malloc et le free, l'application ne passera peut être pas par le free et tu risques également une fuite mémoire. Etc.

    Bref, le code a de grands risque de ne pas être sur

    Pour avoir du code sur, on peut considérer que la gestion des ressources est une responsabilité à part entière. La règle est donc que celui qui alloue une ressource est responsable de la libérer. C'est le gros intérêt des classes C++ (string à la place de char*, vector<T> au lieu de T[], shared_ptr<T> ou unique_ptr<T> au lieu de T*, etc.)
    Tu peux lire le tutoriel de JolyLoic sur les pointeurs intelligent pour mieux comprendre la problématique et comment corriger le problème (si on doit le faire manuellement ; sinon, il est préférable d'utiliser les outils existants) : http://loic-joly.developpez.com/tuto...ointers/#LII-C

    Il faut donc utiliser string en C++ et non char*

    Le seul cas (qui me vient à l'esprit) pour utiliser char* est l'utilisation de bibliothèque C dans un programme C++. Il est alors très très risqué de mélanger du code C et du code C++ ensemble comme tu l'as fait (des string, des malloc, des free, des sprintf, etc.)
    Pour avoir du code sur, il faut isolé le code C à un endroit déterminé et utiliser uniquement du C++ ailleurs. Pour cela, le plus simple est d'utiliser le design pattern wrapper. Au lieu d'avoir des appels de fonctions C n'importe où, tu mets dans un classe dédiée :
    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
    class Clibs_wrapper { // ou un namespace
    public: 
        void foo(const string& str) const { 
            char* cstr = /* conversion */
            c_foo(cstr);
        }
        void foo2(const string& str) const { 
            char* cstr = /* conversion */
            c_foo2(cstr);
        }
    };
     
    Clibs_wrapper w;
    w.foo(str);
    w.foo2(str);
    plutôt que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char* cstr = SAStrToChar(str);
    foo(cstr);
    free(cstr);
    char* cstr2 = SAStrToChar(str2);
    foo2(cstr2);
    free(cstr2);

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 09/12/2010, 20h52
  2. malloc et free pour une liste de 504 bytes
    Par le mage tophinus dans le forum Langage
    Réponses: 2
    Dernier message: 30/10/2008, 11h22
  3. [D2005 VLC] Valeur de retour d'une application
    Par dacid dans le forum Langage
    Réponses: 11
    Dernier message: 04/10/2005, 13h45
  4. Valeur de retour d'une procédure stockée
    Par Rudyweb dans le forum MFC
    Réponses: 4
    Dernier message: 25/02/2005, 17h52
  5. Valeur de retour d'une procédure externe
    Par elekis dans le forum x86 32-bits / 64-bits
    Réponses: 4
    Dernier message: 16/04/2004, 16h45

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