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 :

Malloc et retour de fonction


Sujet :

C

  1. #1
    Membre confirmé Avatar de zentaf
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    122
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 122
    Par défaut Malloc et retour de fonction
    Bonjour à tous,

    J'ai écrit une fonction char * str_ext(char *ch, int start, int end) qui extrait une sous chaine de la chaine d'origine selon les indices. La fonction retourne la sous chaine. J'utilise l'allocation dynamique avec malloc mais je suis obligé de ne pas faire de free() dans ma fonction, je laisse ça à l'utilisateur de ma fonction (chose que j'aime pas trop).

    Pour ce souci, je me demande :

    Si l'utilisateur utilise la fonction de la manière suivante,
    est-ce qu'on doit faire un free() aussi? si oui comment?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char *ch = "Bonjour à tous !";
    char s1[255]="";
    strcpy(s1,str_ext(ch,0,6));
    Rq: admettons que s1 est toujours suffisamment grande pour accueillir la sous chaine.

    au lieu de :

    Merci,
    zentaf.

  2. #2
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    Ca va leaker...
    Tu perds le pointeur qui a été alloué dans str_ext.
    C'est pour ça qu'il "faudrait" faire comme strcpy : demander un tableau de la bonne taille "avant" d'exécuter ton code.

    Mais le but du C et des str*, c'est justement que l'utilisateur gère à sa guise la mémoire ! ^^'
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    est-ce qu'on doit faire un free() aussi?
    Tu réponds toi même à ta question :
    free()[...], je laisse ça à l'utilisateur de ma fonction
    L'utilisateur ne fait pas de free() dans ton exemple, il y a donc une fuite mémoire.

    si oui comment?
    En passant par une variable intermédiaire pour stocker le pointeur retournée par la fonction. Ensuite, tu fais le strcpy() et enfin le free(). Les précautions pour utiliser ta fonction sont les mêmes pour que utiliser strdup().

  4. #4
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Allocation dynamique = libération, tu ne peux pas passer à côté !

    Maintenant, si tu fait une bibliothèque pour gérer les chaînes de caractères, si c'est un gros projet qui englobe peut-être même un plus gros projet, pourquoi ne pas mettre en place une liste chaînée qui garderais la trace de chaque allocations dynamiques. Au chargement du programme, tu appelles (au bon moment mais c'est à toi de le choisir suivant comment tu fais les initialisations primaires) la fonction atexit() dans la quelle tu renseigne une fonction qui va libérer chaque adresse contenue dans ta liste puis pour finir ta liste. Au moment de la fermeture du programme, si l'utilisateur à oublié de libérer certaines choses bin c'est le programme qui s'en occupe.

    Bon je le concède, ça fait pas mal de boulot en plus mais tu peux t'en faire un module réutilisable et l'utiliser pour d'autres projets, je l'ai déjà fait à une époque et c'est prévu en interne à ma bibliothèque de chaînes de caractères (voir ma signature).

    Sinon laisser le soin à l'utilisateur de le faire (de toute manière vaut mieux laisser un moyen de le faire) mais si après y'a des fuites mémoire ce sera pas de ta faute
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  5. #5
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Bonjour,

    A la fin de l'exécution du programme, toutes les ressources mémoires sont libérées ( si je ne dis pas de bêtises ) mais d'autres ressources peuvent ne pas l'être (sémaphore système V ?). Libérer la mémoire avec un atexit() me semble donc un peu superflu.

    Surtout que cette méthode sera inefficace si on recouvre (avec par exemple exec()) le programme par un autre (la mémoire restera allouée il me semble).

    Après, c'est aussi une question de méthode :
    Dès qu'on récupère un pointeur, on se demande s'il faut le désallouer ou non, etc. Et si on a quand même des problèmes de désallocation, Valgrind est là pour nous aider

  6. #6
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Pour la libération c'est selon le système donc il faut partir du principe qu'il ne le fait pas car la norme ne garantie rien à ce niveau
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  7. #7
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    A moins de travailler sans OS pour de l'embarqué je suis d'accord.
    Mais dans ce cas là, la fin du programme correspond très souvent à l'arrêt du micro-contrôleur donc les ressources seront aussi "libérées".

    Dans le cas où on a plusieurs "programmes", il faudrait voir un peu au cas par cas (de toute façon, dans ce cas là on ne pourra presque que faire du cas par cas pour coder).

    Mais dans le cas contraire, c'est l'OS qui gère et est responsable de la mémoire. Donc à moins d'avoir codé soit-même son OS, il libérera toujours la mémoire allouée une fois le programme terminé.


    De toute façon, l'OS est obligé de libérer la mémoire. Si ton programme plante, atexit() ne sera pas appelé, mais il faut quand même libérer la mémoire. Il ne faut pas oublier aussi que c'est l'OS qui alloue la mémoire pour le programme, c'est aussi lui qui le désalloue.

    EDIT : Je regarde aussi rapidement ta bibliothèque.
    Un main.c dans le code d'une bibliothèque et sans main()... faudra m'expliquer

  8. #8
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Bin tu vois, moi j'ai appris que la mémoire allouée dynamiquement ne se libère pas automatiquement par le système, pourquoi tu crois que des langages moderne utilisent des ramasse miettes. Je suis d'accord sur le fait qu'en appelant un free tu demandes au système de libérer et à partir de ce moment là tu ne contrôle plus rien car c'est le système qui va déterminer le meilleur moment pour le faire. Je suis d'accord sur le plantage de l'appli, atexit à ses limites. Concernant ma bibliothèque, main.c n'est là que pour l'implémentation des fonctions, ce n'est pas un programme mais un dll donc je ne vois pas en quoi il faudrait une fonction main(). D'ailleurs même s'il y en avait une, elle serait vide.

    Sauf si tu m'explique à quoi sert exactement la fonction main() dans une bibliothèque partagée, franchement, ça fonctionne très bien sans.
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  9. #9
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Franck.H Voir le message
    Pour la libération c'est selon le système donc il faut partir du principe qu'il ne le fait pas car la norme ne garantie rien à ce niveau
    Je n'ai pas de preuve formelle pour étayer ce que je vais dire, juste des lectures et des discussions avec d'autres développeurs : normalement, tous les OS modernes libèrent la mémoire allouée en fin de programme. Je ne m'inquiète pas trop là-dessus. Ce qui est plus dérangeant dans le fait de ne pas libérer soi-même la mémoire (mettons de côté les ressources allouées dans le main() et trimbalées dans l'ensemble du programme*), c'est que la consommation mémoire augmente alors que c'est pur gaspillage. On code en Java si on veut que ce soit libéré quand on ne s'en sert plus (encore que ^^). * : sauf si un jour on prend le code du main() pour le mettre dans une autre fonction et qu'on ne rajoute pas les free() mais il faudrait être un peu distrait pour faire ça.

    On peut aussi gaspiller les descripteurs de fichiers : http://stackoverflow.com/questions/8...in-a-c-program

    En revanche, le atexit() peut servir à libérer d'autres types de ressources que l'OS ne gère pas. Je prend souvent cet exemple car je l'ai eu une fois sur un système en production et je me suis un peu pris la tête à comprendre le problème : les connexions ouvertes sur des bases de données (BDD). Le programme se connectait à un BDD, créait des prepared statements et oubliait de refermer tout cela en se terminant. Or, ce genre de ressources ne sont pas immédiatement fermées par le SGBD (et bien sûr pas par l'OS qui n'a rien à voir là dedans) et il faut attendre l'expiration du timeout. Du coup, d'autres programmes se ramassaient car il ne pouvait plus ouvrir assez de prepared statements.

    De manière plus générale, il faut être sensibilisé à la gestion des ressources. Les prendre c'est bien, les rendre c'est mieux


    EDIT :
    pourquoi tu crois que des langages moderne utilisent des ramasse miettes
    Cela sert surtout à libérer la mémoire au fur et à mesure

  10. #10
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Citation Envoyé par Franck.H Voir le message
    pourquoi tu crois que des langages moderne utilisent des ramasse miettes.
    Je suis très loin d'être fan des ramasses miettes...
    Utiliser des pointeurs intelligent est bien plus efficace.

    Concernant ma bibliothèque, main.c n'est là que pour l'implémentation des fonctions, ce n'est pas un programme mais un dll donc je ne vois pas en quoi il faudrait une fonction main(). D'ailleurs même s'il y en avait une, elle serait vide.
    Je crois que tu ne m'as pas compris.
    Quand on voit un fichier main.c, on s'attend à trouver une fonction main(). S'il n'y a pas de fonction main(), le nom main.c n'a pas de sens.
    Autant le nommer du nom de l'header : strMachin.c ce qui est beaucoup plus compréhensible et facile pour s'y repérer :
    On sait que l'implémentation des fonctions de l'header X.h se fait dans X.c.
    Avoir un fichier main.c n'a donc pas de sens dans une bibliothèque.
    Si on voit un fichier main.c, on s'attendra alors à avoir des fonctions de tests ou un code minimal pour tester la bibliothèque (et donc la présence d'une fonction main() ).

  11. #11
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Je crois que tu ne m'as pas compris.
    Quand on voit un fichier main.c, on s'attend à trouver une fonction main(). S'il n'y a pas de fonction main(), le nom main.c n'a pas de sens.
    Autant le nommer du nom de l'header : strMachin.c ce qui est beaucoup plus compréhensible et facile pour s'y repérer :
    On sait que l'implémentation des fonctions de l'header X.h se fait dans X.c.
    Avoir un fichier main.c n'a donc pas de sens dans une bibliothèque.
    Si on voit un fichier main.c, on s'attendra alors à avoir des fonctions de tests ou un code minimal pour tester la bibliothèque (et donc la présence d'une fonction main() ).
    Effectivement je ne t'avais pas compris Je suis d'accord par rapport à ce point de vue, disons que le fichier était créé par défaut et que je l'ai simplement gardé c'est tout
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

Discussions similaires

  1. Perte de type en retour de fonction
    Par Bebel dans le forum Langage
    Réponses: 8
    Dernier message: 22/12/2005, 12h54
  2. [syntaxe] tableau et retour de fonction
    Par BainE dans le forum C++
    Réponses: 4
    Dernier message: 08/12/2005, 16h01
  3. Retour de fonction en C
    Par troumad dans le forum Linux
    Réponses: 2
    Dernier message: 06/11/2005, 21h43
  4. Utilisation d'un retour de fonction dans un decode
    Par CFVince dans le forum Oracle
    Réponses: 4
    Dernier message: 20/10/2005, 17h22
  5. Référence en retour de fonction, à transformer en hash
    Par raoulchatigre dans le forum Langage
    Réponses: 4
    Dernier message: 15/07/2005, 14h24

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