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 :

technique pour remettre tous les pointeurs à NULL


Sujet :

C

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut technique pour remettre tous les pointeurs à NULL
    Bonjour, voici 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
    14
    15
    16
    17
    18
    19
    20
    21
     
    #include<stdio.h>
    #include<stdlib.h>
     
    int main(void)
    {
      int * p = malloc(3*sizeof(*p));
      if(p==NULL)
      {
        fprintf(stderr,"erreur\n");
    	exit(1);
      }
     
      int * q=p;
     
      free(q); q=NULL;
      //free(p); p=NULL;
     
      printf("c'est fini\n");
      return 0;
    }
    Si j'enlève la ligne qui est en commentaire, alors mon code tourne jusqu'au bout bien que l'erreur suivante s'affiche sur mon terminal

    out(287) malloc: *** error for object 0x5000f0: double free
    out(287) malloc: *** set a breakpoint in szone_error to debug
    c'est fini
    Je comprends tout à fait que la prgm plante car je libère une zone mémoire déjà libérée. Mais pourquoi le prgm s'exécute jusqu'au bout bien qu'il y ait une erreur pendant son exécution ?

    Y a-t-il une technique pour remettre le pointeur p à NULL : plus généralement, y a-t-il une manière de structurer les données de telle manière que si je libère une zone de la mémoire, alors tous les pointeurs pointant sur celle-ci se mettent à NULL automatiquement ? Ou dois-je tout faire "à la main" ?

    Merci.

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par salseropom Voir le message
    Y a-t-il une technique pour remettre le pointeur p à NULL : plus généralement, y a-t-il une manière de structurer les données de telle manière que si je libère une zone de la mémoire, alors tous les pointeurs pointant sur celle-ci se mettent à NULL automatiquement ? Ou dois-je tout faire "à la main" ?
    Je ne connais que la méthode 'à-la-main', mais il y en a peut être d'autres que je ne connais pas.

    Un 'destructeur' peut pas mal faire le ménage,

    http://emmanuel-delahaye.developpez.com/tad.htm

    mais le pointeur 'ultime' (ou supérieur) devra être forcé à NULL à la main. Je recommande d'ailleurs de le faire avec l'opérateur ',', ce qui rend le code plus 'atomique'...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       xxx_delete(p), p = NULL;
    Pas de Wi-Fi à la maison : CPL

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par salseropom Voir le message
    Y a-t-il une technique pour remettre le pointeur p à NULL : plus généralement, y a-t-il une manière de structurer les données de telle manière que si je libère une zone de la mémoire, alors tous les pointeurs pointant sur celle-ci se mettent à NULL automatiquement ? Ou dois-je tout faire "à la main" ?
    Comme le dit Emmanuel, on initialise toujours les valeurs "à la main" car le C ne fait rien par lui-même. Si t'as plusieurs éléments qui vont ensemble dans une structure, rien ne t'empêche de créer une fonction dédiée à l'initialisation de cette structure que t'appelles quand tu veux.
    Mais moi, j'irai même plus loin en disant que quand on gère bien son code, on sait en permanence quand ses pointeurs sont libres et quand ils ne le sont pas ce qui fait que les mettre à NULL devient inutile...
    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]

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Comme le dit Emmanuel, on initialise toujours les valeurs "à la main" car le C ne fait rien par lui-même. Si t'as plusieurs éléments qui vont ensemble dans une structure, rien ne t'empêche de créer une fonction dédiée à l'initialisation de cette structure que t'appelles quand tu veux.
    Mais moi, j'irai même plus loin en disant que quand on gère bien son code, on sait en permanence quand ses pointeurs sont libres et quand ils ne le sont pas ce qui fait que les mettre à NULL devient inutile...
    Bonjour,
    je fais bien des "constructeurs" et des "destructeurs" dès que je crée une structure. Ca fait qqch du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    T * CreateT(blabla)
    {
      T * t=malloc(sizeof(*T));
      if(==NULL) /* erreur */
      blabla;
    }
     
    void DestroyT(T ** t)
    {
      /* ici je détruits tous les champs (*t)-> et je les remets à NULL*/
      free(*t); *t=NULL;
    }
    Ca revient un peu à faire ce que m'a dit Emmanuel.

    Mais ma question porte sur l'exemple suivant :

    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
     
    typedef struct
    {
      double a;b;
    } S1;
     
    S1 * CreateS1(void)
    {
      S1 * s1=malloc(sizeof(*s1));
      if(s1==NULL) /* erreur */
      return s1;
    }
     
    void DestroyS1(S1 ** s1)
    {
      free(*s1); *s1=NULL;
    }
     
    typedef struct
    {
      double a,b,c;
      S1 * s1;
    } S2;
     
    S2 * CreateS2(S1 * s1)
    {
      S2 * s2=malloc(sizeof(*s2));
      if(s2==NULL) /* erreur */
      s2->s1=s1; /* ici copie de pointeur */  
      return s1;
    }
     
    void DestroyS2(S2 ** s2)
    {
      free(*s2); *s2=NULL;
    }
    donc quand je fais un DestroyS2 et un DestroyS1, mon pointeur s2->s1 ne vaut pas NULL (mais s2 vaut NULL).

    D'où ma question : y a-t-il une technique pour mettre s2->s1 à NULL ? En vous lisant, c'est "à la main", ce que je pensais. Mais c'est un peu "galère" tout de même non ?

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par salseropom Voir le message
    Bonjour,
    je fais bien des "constructeurs" et des "destructeurs" dès que je crée une structure.
    Oui, tu entres dans la technologie objet => c'est une bonne initiative...

    Citation Envoyé par salseropom Voir le message
    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
    typedef struct
    {
      double a,b,c;
      S1 * s1;
    } S2;
     
    S2 * CreateS2(S1 * s1)
    {
      S2 * s2=malloc(sizeof(*s2));
      if(s2==NULL) /* erreur */
      s2->s1=s1; /* ici copie de pointeur */  
      return s1;
    }
     
    void DestroyS2(S2 ** s2)
    {
      free(*s2); *s2=NULL;
    }
    donc quand je fais un DestroyS2 et un DestroyS1, mon pointeur s2->s1 ne vaut pas NULL (mais s2 vaut NULL).
    D'où ma question : y a-t-il une technique pour mettre s2->s1 à NULL ? En vous lisant, c'est "à la main", ce que je pensais. Mais c'est un peu "galère" tout de même non ?
    Ben rien ne t'empêche, dans DestroyS2, d'appeler d'abord DestroyS1...
    Et bien entendu, fidèle à mon opinion, pour moi mettre les pointeurs à NULL reste inutile...

    Petit bug => Ta fonction CreateS2 de type S2* renvoie s1 qui est de type S1*...
    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]

  6. #6
    En attente de confirmation mail
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    133
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 133
    Points : 169
    Points
    169
    Par défaut
    Il y a des techniques (garbage collector, ramasse-miettes en français) mais c'est assez lourd, il faut une liste chainée de tout ce qui référence votre pointeur, donc des fonctions d'allocation, de libération et d'affectation spéciales.

  7. #7
    Membre émérite Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Points : 2 280
    Points
    2 280
    Par défaut
    En poussant un peu plus loin ça doit être faisable, un début peut être :
    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
    56
    57
    58
    59
     
    typedef struct
    {
      double a, b;
    } S1;
     
    S1 * CreateS1(void)
    {
      S1 * s1=malloc(sizeof *s1);
      if(s1 != NULL)
      {
        s1->a = s1->b = 0.0;
      }
      return s1;
    }
     
    void DestroyS1(S1 ** s1)
    {
      if((s1 != NULL) && (*s1 != NULL))/* simple vérif */
      {
        free(*s1), *s1=NULL;
      }
    }
     
    typedef struct
    {
      double a,b,c;
      S1 * s1;
    } S2;
     
    S2 * CreateS2(S1 * s1)
    {
      S2 * s2=malloc(sizeof *s2);
      if(s2 != NULL)
      {
        s2->a = s2->b = s2->c = 0.0;
        if(s1 != NULL)
        {
          s2->s1 = s1
        }
        else
        {
          s2->s1 = CreateS1();
        }
      }
      return s2;
    }
     
    void DestroyS2(S2 ** s2)
    {
      if((s2 != NULL) && (*s2 != NULL))/* simple vérif */
      {
        if((*s2)->s1 != NULL)
        {
          DestroyS1(&(*s2)->s1);
        }
        free(*s2), *s2=NULL;
      }
    }
    "The quieter you become, the more you are able to hear"
    "Plus vous êtes silencieux, plus vous êtes capable d'entendre"

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Oui, tu entres dans la technologie objet => c'est une bonne initiative...



    Ben rien ne t'empêche, dans DestroyS2, d'appeler d'abord DestroyS1...
    Et bien entendu, fidèle à mon opinion, pour moi mettre les pointeurs à NULL reste inutile...

    Petit bug => Ta fonction CreateS2 de type S2* renvoie s1 qui est de type S1*...
    tout à fait, erreur de copier-coller.

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Comme le dit Emmanuel, on initialise toujours les valeurs "à la main" car le C ne fait rien par lui-même. Si t'as plusieurs éléments qui vont ensemble dans une structure, rien ne t'empêche de créer une fonction dédiée à l'initialisation de cette structure que t'appelles quand tu veux.
    Mais moi, j'irai même plus loin en disant que quand on gère bien son code, on sait en permanence quand ses pointeurs sont libres et quand ils ne le sont pas ce qui fait que les mettre à NULL devient inutile...
    Euh, non, ce n'est pas si simple. Il y a des cas de 'send-and-forget', notamment en multi-tâche, où la tâche qui crée l'objet n'est pas celle qui le détruit...
    (pseudo-C)
    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
     
    /* task A */
     
    {
       xxx *p = xxx_create();
     
       /* traitement */
     
       err = envoyer (B, p); /* send ... */
       if (err)
       {
          xxx_delete(p);
       }
       p = NULL; /* and forget */
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    /* task B */
    {
       xxx *p = NULL;
       err = recevoir (&p);
     
       if (!err)
       {
           /* traitement */
     
           xxx_delete(p), p = NULL;
       }
    }
    Pas de Wi-Fi à la maison : CPL

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par salseropom Voir le message
    Bonjour,
    je fais bien des "constructeurs" et des "destructeurs" dès que je crée une structure. Ca fait qqch du genre
    Oui : http://emmanuel-delahaye.developpez.com/tad.htm
    Pas de Wi-Fi à la maison : CPL

  11. #11
    Expert éminent sénior

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Mais moi, j'irai même plus loin en disant que quand on gère bien son code, on sait en permanence quand ses pointeurs sont libres et quand ils ne le sont pas ce qui fait que les mettre à NULL devient inutile...
    Non je suis d'accord avec Emmanuel.

    Il est des cas où (par exemple dans un programme par événements, et/ou en temps réel), on ne sait pas quand les pointeurs sont libres (exemple : si tu fais une liste chainée, ça n'est pas pour rajouter un compteur à coté.. Il faut bien tester si l'élément est NULL ou non).
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    oui, normalement, j'ai fait ce qui est marqué dans tes TAD. D'ailleurs, cela m'a permis de modifier ma classe de matrice (au lieu de faire N+1 allocations, je n'en faisais plus que 2) sans modifier mon "interface")

    Sinon, d'après souviron 34, Emmanuel et Sve@r, j'en déduis que pour remettre TOUS mes pointeurs à NULL (je pense notamment à mes structures temporaires dans lesquelles je fais des copies de pointeurs (et non pas des copies de structures) pour accélérer mon code) je suis obligé de retrousser mes manches et de tout faire "à la main".

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

Discussions similaires

  1. Remettre tous les icônes par défaut
    Par koKoTis dans le forum Windows XP
    Réponses: 4
    Dernier message: 19/12/2006, 19h38
  2. SELECT pour avoir tous les TS d'une database
    Par genio dans le forum DB2
    Réponses: 5
    Dernier message: 21/08/2006, 12h11
  3. mettre des Zero a tous les champ null d'un coup
    Par LesLemmings dans le forum Access
    Réponses: 3
    Dernier message: 14/06/2006, 09h34
  4. Requete pour rechercher tous les parents
    Par richard038 dans le forum Langage SQL
    Réponses: 3
    Dernier message: 28/11/2005, 21h37
  5. Méthode pour supprimer tous les enfants d'un élément
    Par Pymm dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 10/05/2005, 12h10

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