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 :

Problème free() liste chainée


Sujet :

C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 57
    Par défaut Problème free() liste chainée
    Bonjour a tous !

    Voila j'ai un petit problème avec une liste chainée en static, je n'arrive pas a la free ^_^

    La struct en question:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    typedef struct s_hist 
    {
      char		*cmd;
      int		nb;
      int		h;
      int		m;
     
      struct s_hist *next;
      struct s_hist *prev;
    } t_hist;
    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
    void		clear_history(t_hist **history)
    {
      t_hist	*tmp;
     
      while (*history)
        {
          printf("Killing: %s\n", (*history)->cmd);
          tmp = (*history)->prev;
          free((*history)->cmd);    
          free((*history));
          (*history) = tmp;
        }
      (*history) = NULL;
    }
     
    void		history(char *buff, int flag)
    {
      static t_hist	*history = NULL;
     
      if (flag == 0 && buff)
        add_history(&history, buff);
      if (flag == 1)
         clear_history(&history);
      if (flag == 2)
          disp_history(history);
    }
    Les fonctions add_history et disp_history fonctionne bien mais quand je veut clear la list sa ne fonctionne pas.

    je fait disp_history(history) --> la list s'affiche correctement.
    j'appele clear_history(&history) --> il parcours bien toute la list
    je raffiche, rien n'est effacer.

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Dois-tu parcourir selon prev ou selon next ?
    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.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 57
    Par défaut
    Par prev de preference, mais le probleme viens pas du parcours de la liste puisqu'il la parcours bien. (le printf du clear_history() m'affiche bien toute les variables de la liste).

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Mais tu n'invalides pas les pointeurs dedans. En clair, si ça se trouve ça "tombe en marche" et si la liste était assez grande, tu aurais une segfault à la place.

    Essaie un truc de ce genre:
    Code C : 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
    void t_hist_destroy(t_hist *pThis)
    {
    	printf("Killing: %s\n", pThis->cmd);
    	free(pThis->cmd);
    	pThis->cmd = NULL;
    	pThis->next = NULL;
    	pThis->prev = NULL;
    }
     
    void t_hist_delete(t_hist *pThis)
    {
    	if(pThis != NULL)
    	{
    		t_hist_destroy(pThis);
    		free(pThis);
    	}
    }
     
    t_hist* pop_last_history(t_hist **ppLastHistory)
    {
    	t_hist* pRet = *ppLastHistory;
    	if(pRet != NULL)
    	{
    		*ppLastHistory = pRet->prev;
    	}
    	return pRet;
    }
     
    void clear_history(t_hist **ppLastHistory)
    {
    	while (*ppLastHistory)
    	{
    		t_hist_delete(pop_last_history(ppLastHistory));
    	}
    }
    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.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 57
    Par défaut
    Ca ne marche pas malheureusement, on dirait qu'il est impossible de free un static...

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Évidemment. Qu'est-ce qui est static ici?
    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.

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 57
    Par défaut
    dans ma fonction principal de gestion de l'history:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void history(int opt, char *buff)
    {
     static t_hist *history;
     if (opt == 1)
      clear_history(&history);
    if (opt == 2)
      add_history(&history);
    if (opt == 3)
    disp_history(history);
    }
    C'est une fonction a peu pres de cette forme. Ya vraiment aucun moyen de free un static ?

  8. #8
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Ça, ce n'est pas un problème. Si c'est le pointeur qui est statique, ça ne change rien. C'est quand les données pointées sont statiques que ça fait mal.

    Que passes-tu comme chaînes de caractères, par exemple?
    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.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 57
    Par défaut
    Des commandes Shell essentiellement.

  10. #10
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Ce n'est pas ce que je veux dire: Tu ne mets pas de chaînes statiques dans ta liste, au moins?
    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.

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 57
    Par défaut
    non pas de chaine static,

    Le seul endroit ou un static apparait c'est dans la fonction history:

    static t_hist *history;

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Dans ce cas, le code que je t'ai donné ne devrait pas avoir de problème lié à cela (Il a peut-être d'autres problèmes par contre, car je ne l'ai pas testé).
    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.

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 57
    Par défaut
    Pourtant même en copiant exactement ton code ca n'a pas fonctionner. Tant pis je vais me résigner et incluse le t_hist *history dans ma structure principal.

  14. #14
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Sauf que ça ne changera rien au problème. Tu dois chercher la vraie cause plutôt que corriger une cause bidon.

    Poste la totalité du code, par exemple. Quelqu'un aura peut-être une idée en voyant comment tu utilises les diverses fonctions...
    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.

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 57
    Par défaut
    le code est beaucoup trop long pour le posté en entier mais globalement on peut considéré que la fonction history suivant le flag qu'elle reçoit:

    Affiche l'historique --> Elle reçoit juste un (int) flag
    Ajoute un maillon. --> Elle reçoit un (char*) buff et un (int) flag
    Efface l'historique. --> Elle recoit juste un (int) flag

  16. #16
    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 : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par samzorINCA Voir le message
    le code est beaucoup trop long pour le posté en entier
    Essaie de réduire le code et de sortir une version minimale mais compilable qui produit le problème.

    Sinon, met au moins le code de add_history et disp_history.

  17. #17
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 57
    Par défaut
    Le problème c'est que projet c'est le recode d'un shell unix donc pour le moment ya 44 fichiers C et le history c'est un des builtins du shell.

    Le ADD:
    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
    void		add_history(t_hist **history, char *buff, t_hist **key)
    {
      static int	nb;
      time_t	intps;
      t_hist	*tmp;
      struct tm	*timer;
     
      tmp = my_malloc(sizeof(t_hist)); 
      tmp->cmd = my_malloc((strlen(buff) + 1) * sizeof(char));
      strcpy(tmp->cmd, buff);
      tmp->nb = nb++;
      intps = time(NULL);
      timer = localtime(&intps);
      tmp->h = timer->tm_hour;
      tmp->m = timer->tm_min;
      tmp->prev = *history;
      if (tmp->prev)
        tmp->prev->next = tmp;
      *history = tmp;
      *key = *history;
    }
    le DISP:
    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
    void		view_history(t_hist *history, int opt)
    {
      t_hist	*bgn;
      t_hist	*tmp;
     
      tmp = history;
      while (history)
        {
          if (opt)
    	disp_history(history);
          bgn = history;
          history = history->prev;
        }
      history = bgn;
      while (history)
        {
          if (!opt)
    	disp_history(history);
          history = history->next;
        }
      history = tmp;
    }
    Je met des SS du probleme:


    Quand je clean on vois bien que la fonction de parcours du delete fonctionne malheureusement quand je rappelle history la liste n'est toujours pas clean.

  18. #18
    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
    Quelques anomalies :

    - Dans add_history(), le champ next de tmp n'est pas initialisé à NULL (ce qui peut poser problème notamment dans view_history() puisqu'on parcourt à un moment donné via next) : La liste parcourue avec next n'est pas correctement terminée.

    - Dans view_history(), bgn n'est pas initialisé si history == NULL (et le history = tmp; ne sert à rien)

  19. #19
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 57
    Par défaut
    J'ai initialisé les pointeurs en question, toujours pas de free...

  20. #20
    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 : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Au risque de me répéter, peux-tu fournir une version minimale (pas les 44 fichiers) mais compilable et qui reproduit le problème.

    Ici dans ce que tu as donné au fil des messages :
    • Il manque au moins disp_history et my_malloc
    • Il y a une incohérence avec add_history qui prends trois paramètres mais à laquelle tu n'en fournis qu'un ou deux (selon le message dans lequel on regarde) dans la fonction history.

Discussions similaires

  1. Problème de liste chainée
    Par SPACHFR dans le forum Débuter
    Réponses: 2
    Dernier message: 09/09/2009, 15h39
  2. Problème fabrication liste chainée
    Par scary dans le forum Débuter
    Réponses: 2
    Dernier message: 10/03/2009, 12h04
  3. Problème de listes chainées
    Par line86 dans le forum C
    Réponses: 5
    Dernier message: 20/04/2008, 10h30
  4. Probléme avec Liste Chainée
    Par Lucas42 dans le forum C
    Réponses: 6
    Dernier message: 24/01/2008, 20h15
  5. un probléme de liste chainé simple
    Par seifdev dans le forum C
    Réponses: 15
    Dernier message: 02/04/2007, 16h36

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