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 :

Retour aux sources, la liberation de memoire


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Par défaut Retour aux sources, la liberation de memoire
    Bonjour,

    Depuis que j'ai commence la programmation, quand je veux remplir une chaine dans une autre fonction j'envoie le type fonction_de_remplissage(str), et pour liberer ou allouer de la memoire, j'envoie create_or_free(&str).

    Je pense ne pas me tromper pour l'allocation de memoire, mais je commence a voir de serieux doutes pour le free, vu que malloc renvoir un pointeur sur adresse, je devrais pouvoir envoyer le pointeur directement, non ? Free ne retournant pas de valeur, et quand on le re print, meme en ayant free on a encore les donnees, j'aimerais que quelqu'un confirme mes doutes afin d'eviter toute perte de memoire a l'avenir.

    J'aimerais faire de la facon suivante, car actuellement je fais que des void(&str) pour creer et liberer mes chaines (en recuperant des char *(*str), et autres types, et je voudrais profiter des return en restant dans le 0 perte de memoire.

    Merci !

    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
     
    char *create(char *str)
    {
    int len;
     
    len = 4;
    str = malloc(len + 1 * sizeof(*str));
    return (str);
    }
     
    void  full(char *s1, char *s2)
    {
    strcpy(s1, s2);
    }
     
    void lib(char *str)
    {
    free(str);
    }
     
    int main()
    {
    char *str = NULL;
     
    str = lib(full(create(str), "toto"));
    return(0);
    }
     
    /* AU LIEU DE CA, VOILA CE QUE JE FAIS, J'AI JAMAIS EUT DE PROBLEME, MAIS JE TROUVE CA SUPER SALE ! */
     
    void create(char *(*str))
    {
    int len = 4;
    str = malloc(len + 1 * sizeof(*(*str)));
    }
     
    void  full(char *s1, char *s2)
    {
    strcpy(s1, s2
    }
     
    void lib(char *(*str))
    {
    free(*str);
    }
     
    int main()
    {
    char *str = NULL;
     
    create(&str);
    full(str, "toto");
    lib(&str);
    return(0);
    }

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 264
    Billets dans le blog
    177
    Par défaut
    Bonjour,

    J'ai eu un peu de mal à comprendre la question. Mais comme première idée qui m'est venu à la tête, c'est que si vous avez des doutes sur les fuites de mémoire ( et autre débordement ), et que vous êtes sous Linux, utilisez valgrind.
    ( c'est une petite merveille cet outil )

    Maintenant, revenons au code.
    Les deux codes sont juste ( sinon, j'ai un peu mal vu ).
    Dans le premier, je trouve la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    str = lib(full(create(str), "toto"));
    Assez barbare. En fait, elle est fausse. Pourquoi? Le compilateur devrait le dire d'ailleurs .
    Simplement car lib() prend un pointeur sur un char* ( c'est partie d'une bonne intention ) mais que full(), ne retourne pas de pointeur sur un char* ( ce qui est normale ). Du coup, lib attrappe une valeur indeterminée comme paramètre, et va faire une libération de quelque chose d'indéterminée. Ici il y aura des erreur de segmentation, ou autre.
    Et puis même chose, pour str, car lib() return un void soit rien, soit str aura une valeur indéterminé.

    Maintenant, le deuxième code, à une chose inutile.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void lib(char *(*str))
    {
    free(*str);
    }
    Dans ce cas là, il faut mieux faire ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void lib(char *str)
    {
    free(str);
    }
    ou alors plus sécuritaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void lib(char *(*str))
    {
    free(*str);
    *str = NULL;
    }
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    str = lib(full(create(str), "toto"));
    Assez barbare. En fait, elle est fausse. Pourquoi? Le compilateur devrait le dire d'ailleurs .
    Simplement car lib() prend un pointeur sur un char* ( c'est partie d'une bonne intention ) mais que full(), ne retourne pas de pointeur sur un char*
    Exact, je me suis concentre sur la liberation de memoire, c'est un oublie de ma part, je comptais en effet retourner un char *.

    Citation Envoyé par LittleWhite Voir le message
    Maintenant, le deuxième code, à une chose inutile.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void lib(char *(*str))
    {
    free(*str);
    }
    Dans ce cas là, il faut mieux faire ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void lib(char *str)
    {
    free(str);
    }
    Voila qui répond a mes doutes ! Merci beaucoup.

    Citation Envoyé par LittleWhite Voir le message
    ou alors plus sécuritaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void lib(char *(*str))
    {
    free(*str);
    *str = NULL;
    }
    Es ce vraiment plus sécuritaire ? Ou tu veux dire, par rapport a mon code peut etre ? C'est en gros ma façon de faire, mais je trouve ca assez sale...

    Merci encore, bonne journee !

  4. #4
    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
    Disons que c'est plus propre de mettre à NULL un pointeur qui a été 'free'. Au moins tu sais qu'il est 'vide'.

    Après je ne suis pas sûr que cette écriture soit correcte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void lib(char *str)
    {
    free(str);
    }
    Après, peut-être que je me trompe.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Par défaut
    C'est la question que je me pose, car faire:

    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 *full_str(char *str)
    {
    str = malloc(2 *sizeof(*str));
    str[0] = 'O';
    str[1] = '\n';
    return (str);
    }
     
    int main()
    {
    char *str = NULL;
     
    str = full_str(str);
    free(str);
    }
    full_str renvoie un pointeur sur adresse si j'ai bien compris, donc dans le main on fait pointer un pointeur, sur un pointeur sur adresse, ce qui me semble etre source d'ennuis pour free notamment...

    Ou y a t'il une difference que de faire:

    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
    char *full_str()
    {
    char *s2 = NULL;
     
    s2 = malloc(2 * sizeof(*s2));
    s2[0] = 'O';
    s2[1] = '\n';
    return (s2);
    }
     
    int main()
    {
    char *str = NULL;
     
    str = full_str();
    free(str);
    }

  6. #6
    Expert confirmé
    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
    Par défaut
    Les deux codes sont faux et pour la même raison. Prenons le premier en exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    str = malloc(sizeof(*str));
    str est un char * donc *str est un char. Alors, sizeof(*str) est la même chose que sizeof(char) qui vaut toujours 1.
    Cette ligne est donc équivalente à
    Cette allocation est bien sûr insuffisante pour stocker tes caractères.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Par défaut
    Oui

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    str = malloc(2 * sizeof(*str);
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    s2 = malloc(2 * sizeof(*s2);
    mais c'est sur la suite que j'ai voulut porter le sujet, cela dit tu as raison de le souligner (post edite et corrige).

  8. #8
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par Pouet_forever Voir le message
    Après je ne suis pas sûr que cette écriture soit correcte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void lib(char *str)
    {
    free(str);
    }
    Ah et pourquoi ?

    Citation Envoyé par student_ Voir le message
    full_str renvoie un pointeur sur adresse si j'ai bien compris, donc dans le main on fait pointer un pointeur, sur un pointeur sur adresse, ce qui me semble etre source d'ennuis pour free notamment...
    Qu'entends-tu par pointeur sur adresse ?

    Sinon, aussi bien str dans main que le retour de full_str() sont des pointeur sur char.
    • str vaut NULL avant l'appel de full_str() puis contient l'adresse retourné par malloc() après le retour de full_str() (ou NULL en cas d'erreur).
    • Le retour de full_str est l'adresse retourné par malloc() (ou NULL en cas d'erreur).


    Mais il n'y a pas de problème ici (enfin mis à part la remarque de diogene et l'absence de vérification de la valeur de retour de malloc()). Et en particulier rien qui ne pose problème lors de l'appel à free().

    Fonctionnellement, les deux codes sont équivalent.

    Au passage,
    • Si full_str() est censé, comme son nom l'indique, créer une chaîne de caractère, il faut réservé un char de plus et y mettre le \0 terminal.
    • Le second code pourrais s'écrire plus simplement :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    char *full_str()
    {
       char *s2 = malloc(2 * sizeof(*s2));
       s2[0] = 'O';
       s2[1] = '\n';
       return (s2);
    }
     
    int main()
    {
       char *str = full_str();
       free(str);
    }

  9. #9
    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
    Citation Envoyé par gl Voir le message
    Ah et pourquoi ?
    Je sais pas, j'aurais tendance à mettre char *(*str) aussi. Mais au final en mettant juste *str tu ne remets pas ton pointeur à NULL (c'est pour ça que ça m'a perturbé ).

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Par défaut
    J'ai mit un '\n' au lieu d'un '\0' en editant le post, desole erreur d'inattention...

    Sinon, moi ce qui me gene c'est assez abstrait, je l'illustre en commentaire dans le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void full_str(char *str)
    {
    str = malloc(2 * sizeof(*str));
    str[0] = 'A';
    str[1] = '\0';
    }
    
    int main()
    {
    char *str = NULL;
    full_str(str);
    putstr(str); /*Voir ci dessous*/
    }
    *Ici, on peut afficher la chaine soit:
    1) Si on retourne str de full_str().
    2) Si on envoie &str a full_str en recuperant un char *(*str).

    Pour resumer, on ne peut pas acceder au contenu de la chaine, mais nous pouvons pourtant acceder a son espace memoire en faisant un free(), esce parce que la fonction malloc renvoie un pointeur vers l'adresse de str ? Desole d'insister mais je n'ose plus coder tant que je ne maitriserai pas la question^^

    Merci encore pour les explications, bonne fin de soiree.

  11. #11
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    Pour resumer, on ne peut pas acceder au contenu de la chaine, mais nous pouvons pourtant acceder a son espace memoire en faisant un free(),
    free libère simplement la zone de mémoire allouée, ce qui ne veut pas dire que son contenu est effacé pour autant mais que cette zone pourra ultérieurement être réutilisée par un autre malloc. Si tu accèdes à une zone mémoire que tu as libérée, c'est dangereux car là alors plus rien ne peut t'assurer que les données présentes sont toujours intactes. De plus, un simple accès risque de faire planter ton programme.

    Pour imager (juste pour expliquer l'idée), deux exemples un peu HS :
    1 ) C'est un peu la même chose lorsque tu effaces un fichier de ton disque dur. Si aucun autre fichier n'est recréé ou modifié, on pourra toujours lire le contenu du fichier effacé. Effacer un fichier ne veut pas dire "effacer son contenu", mais cela veut simplement dire que les blocs qui lui étaient réservés sont libérés, c'est-à-dire qu'ils pourront ultérieurement être réutilisés pour un autre fichier. Tant que rien de nouveau n'a été créé, les données sont toujours là.
    2 ) Autre exemple. Lorsque tu sors d'une fonction qui contient des variables locales, ces variables sont toujours stockées sur la pile mais on ne doit surtout pas y accéder par la suite car à tout moment de nouvelles données peuvent écraser l'ancien contenu, d'où la raison pour laquelle il ne faut jamais renvoyer à la fonction appelante un pointeur vers un objet local (à moins qu'il soit statique, mais là c'est un autre débat).

    Pour résoudre ton problème (enfin... à vrai dire, je ne comprends pas ce que tu ne comprends pas ici), tu donnes doit-même la réponse :
    Ici, on peut afficher la chaine soit:
    1) Si on retourne str de full_str().
    2) Si on envoie &str a full_str en recuperant un char *(*str).
    Par conséquent, dans le code que tu viens de donner, la fonction appelante (ie main) ne connaîtra jamais ce que malloc a retourné, et sa variable locale str restera désespérément à NULL. Par contre, la mémoire allouée est toujours allouée (que tu restes dans la fonction ou que tu en sortes), et son contenu ne changera plus, et ce tant que le programme tournera. Mais comme la valeur du pointeur est perdue, cela correspond alors à une fuite de mémoire, puisqu'il n'y aura plus aucun moyen de libérer cette mémoire jusqu'à ce que le programme se termine.

    esce parce que la fonction malloc renvoie un pointeur vers l'adresse de str ?
    malloc renvoie simplement un pointeur vers la mémoire allouée. Dans ton exemple, il y a 2 octets d'alloués :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    2 * sizeof(*str) /* = 2 * 1 = 2 */
    Le premier octet de la mémoire allouée est rempli par 'A' et le second par '\0'.

    Desole d'insister mais je n'ose plus coder tant que je ne maitriserai pas la question^^
    Mais le problème, c'est que je ne comprends pas ce que tu ne comprends pas. Et apparemment, je ne suis pas le seul.

  12. #12
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 264
    Billets dans le blog
    177
    Par défaut
    Citation Envoyé par student_ Voir le message
    Desole d'insister mais je n'ose plus coder tant que je ne maitriserai pas la question^^
    C'est bien dommage, c'est en codant que l'on devient coder.

    Un peu plus serieusement, c'est en faisant plein d'esperimentation, que l'on apprend. Comme je l'avais conseille au tout debut, l'utilisation de valgrind aide a voir les fuites de memoires ( et meme l'acces a de la memoire non alloue ). Cela est tres pratique, et je pense que cela peut aider.

    Autre chose, presonnellement, je ne saisi pas la difference entre:
    et
    ( Du moins, pas dans une declaration).

    Finallement, et je pense qu'il faut clarifier les choses un peu (ou du moins repeter ce qui a deja etait dit),
    malloc retourne un pointeur sur de la memoire allouee. Si on veut retourner ce pointeur en dehors d'une fonction, nous avons de choix:
    - Un simple return, aui copiera le pointeur.
    - Par passage d'un pointeur en parametre de la fonction.
    Pour la deuxieme methode, il faut retenir, que nous ne pouvons modifier que la valeur pointe par le pointeur passe en parametre. Dans un cas simple, pour retourner un int avec cette methode, on donne un pointeur sur un int, afin de changer la valeur pointee.
    Ici, comme nous voulons retourner un pointeur, nous devons donc passer un pointeur sur un pointeur afin de changer la valeur de la valeur pointee.

    Pourquoi que si on ne le fait pas, cela marche pas?

    Car dans un code, on l'on envoie juste un pointeur (comme un pointeur sur un char, par exemple), ce pointeur est copier (temporairement) lors de l'appel de la fonction. Donc, si on essaie de changer ce parametre, par la valeur retourner par malloc, en fait, on ne change que une copie, qui ne sortira jamais du contexte de la fonction (car c'est une copie temporaire).

    En esperant avoir etait clair,

    Donc le code de ce sujet devient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void full_str(char **pStr)
    {
    *pStr = malloc(2 * sizeof(*(*str))); // Et oui, ici on change la valeur pointer par le pointeur qui est en parametre.
    // Et c'est la que je me dit, pourquoi nous nous embetons avec ce sizeof
    // Alors que l'on pourrait juste mettre sizeof(char), ce qui nous simplifirai la vie. (Du moins cela la facilite)
    *pStr[0] = 'A'; // On continue les changements de la meme facon
    *pStr[1] = '\0';
    }

    ( Toute mes excuses pour le manque d'accent, tout comme vous, je trouve le clavier anglais pauvre )
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Par défaut
    Pour repondre au post le LittleWhite, ce que tu as fait c'est exactement ma facon de faire, (grace a pouet_forever qui m'avait explique cette methode il y a bien longtemps d'ailleurs^^) seulement j'aimerais optimiser mon code en faisant des "cascades de fonctions"
    ==> func1(func2(func3(func4))));
    et pour cela j'aimerais utiliser le return, car en faisant comme ca, la quasi entite de mes fonctions son de type (void).

    Tu parles de copie temporaire, c'est justement ce qui me fait peur, le return est donc une copie de pointeur, comme vous me l'avez conseille, je vais faire une batterie de tests sur valgrind cette aprem, merci de m'avoir eclaire !

    Merci aussi pour votre patience ! Bonne journee.

  14. #14
    Expert confirmé
    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
    Par défaut
    LittleWhite :
    Autre chose, presonnellement, je ne saisi pas la difference entre:...
    Il n'y en a pas !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void full_str(char **pStr)
    {
    *pStr = malloc(2 * sizeof(*(*pstr)));
    ....
    Moi, ce qui me gêne dans cette écriture, c'est qu'elle laisserait supposer que la quantité allouée dépend de *pstr, ce qui n'est pas le cas (mais n'y a t-il pas une confusion à ce sujet de la part du posteur qui penserait obtenir la longueur de la chaine passée en argument de cette façon ?) et je préfère de beaucoup clarifier la situation en écrivant qu'on a toujours
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void full_str(char **pStr)
    {
    *pStr = malloc(2);
    ....

  15. #15
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    seulement j'aimerais optimiser mon code en faisant des "cascades de fonctions"
    ==> func1(func2(func3(func4))));
    Tu n'as qu'une solution dans ce cas : les fonctions doivent à la fois recevoir un paramètre et retourner une valeur. Car la valeur retour d'une fonction doit servir de paramètre pour la fonction suivante qui sera appellée, etc.

    et pour cela j'aimerais utiliser le return, car en faisant comme ca, la quasi entite de mes fonctions son de type (void).
    Certainement pas, comme je viens de dire. Pour reprendre ton exemple, la fonction fonc3 a besoin d'un paramètre, mais devra aussi renvoyer une valeur qui sera utilisée comme argument pour fonc2, etc.

    Tu parles de copie temporaire, c'est justement ce qui me fait peur, le return est donc une copie de pointeur
    return renvoie la valeur d'un objet. Dans notre cas, il s'agit de la valeur du pointeur (et non l'objet pointeur lui-même). En C, il n'y a pas de notion de référence comme en C++.

    Dans cet exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char *full_str(void)
    {
       char *s2 = malloc( 2 );
       s2[0] = 'O';
       s2[1] = '\0';
       return s2;
    }
    , la fonction renvoie la valeur du pointeur s2, qui correspond aussi à la valeur retournée par malloc. Ce n'est pas l'objet s2 qui est retourné mais sa valeur. Une fois sorti de la fonction, il sera alors toujours possible de libérer la mémoire allouée, puisque la fonction retourne bien l'adresse de la mémoire allouée.

    De même, dans un code tel que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void full_str(char **pStr)
    {
    *pStr = malloc( 2 );
    **pStr = 'A';
    *(*pStr + 1 ) = '\0';
    }
    (...)
    char * ptr ;
    full_str(&ptr);
    , pStr est un objet local (temporaire donc, qui sera détruit à la fin de la fonction), en l'occurrence un pointeur de pointeur dont sa valeur correspond à l'adresse mémoire où est stocké le pointeur ptr, qui correspond donc à l'adresse où est stockée la valeur de ptr.

    On résume :
    pStr est un pointeur, dont sa valeur correspond à l'adresse où est stocké la valeur du pointeur ptr
    *pStr correspond alors à la valeur de ptr et non plus à l'adresse où cette valeur est stockée.
    **pStr correspond à ce qui est situé à l'adresse correspondante à la valeur de ptr, c'est-à-dire à 'A'.


    (Après, je ne sais pas si j'ai bien cerné ce qui te pose problème ? J'ai peut-être mal compris ta question ?)

    EDIT :
    Par contre, entre nous, je ne comprends pas l'utilité d'un code tel que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    detruire_objet(initialiser_objet(creer_objet());
    . A moins que c'était seulement à titre d'exemple bien sûr...

Discussions similaires

  1. [olivier.taranis] retour aux sources
    Par olivier.taranis dans le forum Présentations
    Réponses: 3
    Dernier message: 23/04/2014, 09h12
  2. Retour aux sources
    Par F@bien.fd dans le forum Débuter
    Réponses: 10
    Dernier message: 23/09/2011, 11h59
  3. [Débat] MVC : le retour aux sources ?
    Par CUCARACHA dans le forum ASP.NET
    Réponses: 19
    Dernier message: 11/06/2009, 09h34
  4. liberation de memoire d une fenetre modale
    Par ienien dans le forum MFC
    Réponses: 6
    Dernier message: 04/01/2006, 13h53
  5. Réponses: 6
    Dernier message: 24/10/2005, 19h12

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