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 :

Un petit problème de free


Sujet :

C

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut Un petit problème de free
    Bonjour,

    Apparamment, il y a une petite subtilité avec les pointeurs que je n'ai pas compris, et que j'aimerais bien comprendre. Je dispose d'une liste codée comme suit :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct Lst
    {
      Node* m_Content;
      struct Lst * m_Next;
    } Liste;
    J'ai donc un pointeur sur le premier élément (m_First) , que je conserve. Mais j'ai aussi un autre pointeur pointant a peu près n'importe dans la liste : m_Cur;

    Réguliérement, je veux libérer le contenu (ie : libérer m_Content) pour un élément sans casser la chaine : m_Content est alors mis à NULL, mais m_Next reste intact, et l'élément précédent continu de pointer ce "noeud vide".
    Si je copie m_First, parcours la liste jusqu'à mon élément, et libére, ca marche.
    Mais si je fais free(m_Cur->m_Content), deux cas : soit ca plante (alors que je me suis assuré avant que m_Content était non nul...) soit ca marche, mais ca n'a aucun effet sur ma liste ! Comme si m_Cur->m_Content n'était qu'une copie de ce que je veux supprimer, située ailleurs, que cette copie a été bien libérée, mais pas l'original ! Où est la subtilité ?


    Et d'une manière générale, quelles sont les causes possibles d'un plantage (genre seg fault) lors d'une instruction free(ptr), PRECEDEE d'un if( !ptr ) (et suivi d'un ptr = NULL ) ?

    Merci

    Cordialement

  2. #2
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par delire8 Voir le message
    Apparamment, il y a une petite subtilité avec les pointeurs que je n'ai pas compris, et que j'aimerais bien comprendre. Je dispose d'une liste codée comme suit :
    Montre ton code.

  3. #3
    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
    Mais si je fais free(m_Cur->m_Content), deux cas : soit ca plante (alors que je me suis assuré avant que m_Content était non nul...) soit ca marche, mais ca n'a aucun effet sur ma liste
    free(NULL) est possible et ne plante pas (mais évidemment ne fait rien) .
    La question n'est pas de savoir si m_Content est NULL, mais si
    - m_Cur est NULL
    - m_Cur n'est pas NULL mais pointe ailleurs que sur un élément de la liste ou sur un élément de la liste déjà détruit
    - m_Cur n'est pas NULL et pointe sur un élément de la liste et m_Content n'est pas NULL mais n'a pas été initialisé ou pointe sur un objet déjà détruit.

    Pour en savoir plus, il faudrait voir le code incriminé.

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par delire8 Voir le message
    Et d'une manière générale, quelles sont les causes possibles d'un plantage (genre seg fault) lors d'une instruction free(ptr), PRECEDEE d'un if( !ptr ) (et suivi d'un ptr = NULL ) ?
    Le free(ptr) plantera si
    - ptr contient une adresse invalide autre que NULL
    - ptr a déjà été freeé (super barbarisme) auparavant

    Le "if(! ptr)" est généralement inutile car tu te dois, à chaque moment de ton code, savoir quels sont les pointeurs valides et donc n'appeler "free()" que quand il faut. Bon, il y a les exceptions (style une fonction de libération générale qui est appelée dans tous les cas alors que tout n'est pas forcément alloué) où ça se justifie mais ça reste généralement exceptionnel.

    Le "ptr = NULL" est à mon avis pareillement inutile pour les mêmes raisons (si je l'alloue plus tard, alors le NULL est inutile et si je l'alloue pas, alors c'est que je m'en sers pas donc le NULL reste inutile) mais d'une part cet avis n'engage que moi et d'autre part là aussi il peut y avoir des exceptions comme ci-dessus.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    La remise à NULL n'est inutile que si le programme n'a aucun bug, ce qui évidemment n'est pas garanti.

    Donc, on remet à NULL, ce qui permet généralement:
    • De contourner les problèmes de double-free
    • De détecter plus facilement un accès au pointeur après destruction.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par diogene Voir le message
    free(NULL) est possible et ne plante pas (mais évidemment ne fait rien) .
    .
    Peut-etre que cela a ete modifie, mais sur certains systemes (HPUX et SunOS en particulier, en tous cas il y a une dizaine d'annees) free(NULL) entrainait un crash (coredump).

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    On peut espérer que ça ait été corrigé depuis, car la norme exige que free(NULL) ne plante pas.

    Par contre, fclose(NULL) est un comportement indéfini.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre éprouvé Avatar de siegfried64
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    78
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Maroc

    Informations forums :
    Inscription : Novembre 2007
    Messages : 78
    Par défaut
    Citation Envoyé par delire8 Voir le message
    soit ca marche, mais ca n'a aucun effet sur ma liste ! Comme si m_Cur->m_Content n'était qu'une copie de ce que je veux supprimer, située ailleurs, que cette copie a été bien libérée, mais pas l'original ! Où est la subtilité ?
    quand on appelle la fonction free(m_Cur->m_Content), effectivement elle libere la zone mémoire pointé et la rend à l'os, mais m_Cur->m_Content pointe toujours sur cette adresse mémoire, lors de ton parcours de liste tu essaie d'y acceder, donc soit tu y retrouve tes données intactes parceque cette zone mémoire n'a pas été utilisé par autre programme d'où l'absence de tout effet sur ta liste, soit elle est utilisé donc ton application plante. Enfin c'est ce que je pense, aprés la liberation tu devrais peut etre faire :

Discussions similaires

  1. un petit problème d'algo
    Par supertramp dans le forum Algorithmes et structures de données
    Réponses: 22
    Dernier message: 12/10/2004, 20h13
  2. Petit problème de décimales !
    Par ridan dans le forum Langage SQL
    Réponses: 5
    Dernier message: 11/09/2004, 21h24
  3. Réponses: 17
    Dernier message: 13/07/2004, 20h37
  4. petit problème premier plan, arrière plan
    Par gros bob dans le forum OpenGL
    Réponses: 4
    Dernier message: 19/04/2004, 12h00
  5. [jointure] Petit problème sur le type de jointure...
    Par SteelBox dans le forum Langage SQL
    Réponses: 13
    Dernier message: 13/02/2004, 18h55

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