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 :

Pointeurs nus et code « sûr »


Sujet :

C++

  1. #1
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut Pointeurs nus et code « sûr »
    Bonjour.
    Tout d'abord, merci de ne pas me crier dessus à la vue du sujet…

    J'aimerais avoir des pistes pour maximiser la sûreté d'un code qui utilise des pointeurs, alors qu'on n'a pas la possibilité d'utiliser des pointeurs intelligents.

    Je pose cette question dans le cas général, mais pour l'application qui m'intéresse il y a beaucoup de pointeurs (pour usage polymorphique), stockés dans des conteneurs.
    Certains pointeurs sont stockés dans plusieurs conteneurs en même temps, mais normalement, un seul de ces conteneurs est chargé de désallouer la mémoire.
    Enfin je veux dire que c'est lorsque l'on doit en détruire un en particulier (de tous ceux qui peuvent contenir le pointeur en question) que l'on libère la mémoire.
    Ce n'est pas moi qui ai écrit le code, donc je ne sais pas exactement comment ça a été géré, mais je suis censé l'améliorer…

    Merci d'avance.

    Édit: Je ne devais pas être très clair sur le stockage des pointeurs, alors j'ai clarifié.

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Maitriser la politique de copie de tes objets : faire du RAII où tu le peux, rendre non copiable tout ce qui peut l'être, et expliciter la politique de copie là où tu ne peux rendre non copiable.
    Voilà les premières idées qui me viennent.

  3. #3
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 636
    Par défaut
    Je plussoie l'approche de 3D...

    Je me demande d'ailleurs si je n'irais pas jusqu'à déclarer le destructeur de la classe de base manipulée par la classe qui doit gérer la durée de vie des objets polymorphes, et à déclarer cette dernière comme amie de la première

    Cela pourrait limiter fortement les risques de tentatives de double libération
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 48
    Par défaut
    Bonjour,
    Étant de nature parano, je met assez systématiquement des conteurs d'objets.
    Cela me permet de vérifier - au moins - que la mémoire est correctement désallouée.
    J'utilise une classe template count... dont je dérive les classes que je souhaite vérifier

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    template<class T>
    count
    {
      protected:
        count(){++count_;}
        virtual ~count{--count_;}
    private:
      static int count_;
    };
     
    template<class T>
    int count<T>::count_ = 0;
    Ça casse pas deux pattes à un canard, mais cela peut servir...

  5. #5
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Je me demande d'ailleurs si je n'irais pas jusqu'à déclarer le destructeur de la classe de base manipulée par la classe qui doit gérer la durée de vie des objets polymorphes, et à déclarer cette dernière comme amie de la première
    Hum…
    Pas sûr de comprendre où tu veux en venir…

    Citation Envoyé par omc24 Voir le message
    J'utilise une classe template count... dont je dérive les classes que je souhaite vérifier
    Ça a l'air plutôt intéressant, mais je n'arrive pas à voir comment l'utiliser…

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 48
    Par défaut
    Bonjour,
    Si tu veux vérifier une classe "A", tu n'as qu'à dériver cette classe de "count<A>" et cela fonctionne tout seul.
    Comme le constructeur de count<A> ne prend pas de paramètre, tu n'as pas besoin de l'appeler depuis la zone d'initialisation des données membres du constructeur de A... Le compilo le fait pour toi.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    class A : public count<A>
    {
    ....
    }

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 636
    Par défaut
    Citation Envoyé par Steph_ng8 Voir le message
    Hum…
    Pas sûr de comprendre où tu veux en venir…
    en fait, j'aurais du dire: le destructeur de la classe de base / des classes abstraites protégé (virtuel) et ceux des classes dérivées / instanciables privées, en déclarant la classe responsable de leur durée de vie amie de toutes ces classes.

    De cette manière, il n'y a que la classe responsable de la durée de vie qui est en mesure de détruire tes objets, c'est aussi simple que cela.

    Si tu essaye, par inadvertance, d'invoquer delete sur un pointeur depuis "ailleurs que la classe amie", le compilateur se plaindra que le destructeur et privé dans le contexte, et sortira sur une erreur

    Mais cela n'est malgré tout possible qu'avec des hiérarchie d'ampleur limitée, et il faudra malgré tout veiller à ce que la classe responsable de la durée de vie de l'objet ne profite pas de l'amitié qui l'unit au dit objet pour aller jouer avec ce qu'elle ne devrait pas
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    @omc24 Si j'ai bien compris, ça te sert à compter le nombre d'instantes d'une classe donnée.
    Mais je ne vois pas comment l'utiliser en pratique, puisque ton compteur n'est pas accessible.
    Et que se passe-t-il quand il arrive à 0 ?
    Ou quand il n'arrive pas 0 à la fin du programme ?

    @koala01 Ok, je crois que je vois mieux.
    Enfin ça protège des doubles déallocations, mais pas des fuites mémoires.
    Bon, c'est déjà pas mal.
    C'est à la classe « amie » de s'occuper de bien libérer les ressources.

    @3DArchi Au fait, merci pour tes conseils.
    J'avais déjà regardé rapidement la partie sur le RAII dans la FAQ il y a quelques temps, mais sans vraiment entrer dans les détails.
    Je vais m'y replonger…

  9. #9
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Au fait, quand une exception non interceptée est lancée, le programme est interrompu brusquement, non ?
    Du coup, les objets, même statiques, ne sont pas détruits, si je ne m'abuse ?

    Alors finalement, ça veut dire quoi « exception-safe » ?
    « Sûr pour les exceptions capturées » ?

    Si c'est bien le cas, j'ai du mal à voir comment les pointeurs intelligents permettent de se passer de vérifier que la mémoire a correctement été allouée.

  10. #10
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 636
    Par défaut
    De toutes manières, le système s'occupe (généralement plutôt bien) de "ramasser les miettes" de mémoire non libérées au moment où l'application est quittée, que ce soit sur demande de l'utilisateur ou suite à une erreur quelconque qui aurait provoqué le "plantage" de l'application.

    L'exception safty a pour but de t'assurer, si une exception plus ou moins prévisible survient, que, si ton système est dans un état cohérent avant que l'exception ne survienne, il restera dans un état cohérent si l'exception est récupérée et traitée.

    Mettons, simplement, que tu utilises une entrée utilisateur pour obtenir un nom de fichier à lire.

    Ton programme est dans un état cohérent avant que tu ne tente de lire le fichier (ou du moins, nous supposerons que c'est le cas).

    Mais, si l'utilisateur se trompe dans le nom du fichier, ou que le fichier est déjà "verrouillé" par le système, tu ne pourra pas l'ouvrir, et tu obtiendra une jolie exception.

    La solution est, finalement, assez simple, et tu peux donc très facilement gérer ce genre de problème, et donc éviter que ton programme ne plante pour une telle c...rie.

    En travaillant "exception safe", tu t'assure, si cette exception survient, soit l'ensemble des modifications apportées à l'état du programme seront annulées, soit que ton programme se trouvera dans un état cohérent en ayant appliqué un certains nombre de modifications qui seront prise en compte
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 48
    Par défaut
    Si j'ai bien compris, ça te sert à compter le nombre d'instantes d'une classe donnée.
    Oui

    Mais je ne vois pas comment l'utiliser en pratique, puisque ton compteur n'est pas accessible.
    Il suffit de rajouter un accesseur
    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
     
    template<class T>
    count
    {
      public:
        static int GetInstanceNumber(){return count_;}
      protected:
        count(){++count_;}
        virtual ~count{--count_;}
    private:
      static int count_;
    };
     
    template<class T>
    int count<T>::count_ = 0;

    Et que se passe-t-il quand il arrive à 0 ?
    Cela veut dire qu'il n'y à plus d'instance de la classe "A".

    Ou quand il n'arrive pas 0 à la fin du programme ?
    C'est qu'il y a problème. Tous les objets n'ont pas été détruit. Ou alors, il y a des objets "statiques" qui seront détruit à la sortie du main() et dans ce cas c'est normal.

  12. #12
    Membre expérimenté Avatar de MacPro
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    367
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Novembre 2007
    Messages : 367
    Par défaut
    Citation Envoyé par omc24 Voir le message
    Ça casse pas deux pattes à un canard, mais cela peut servir...
    Ma réponse n'a rien d'informatique mais je la donne quand même :

    On dit que ça casse pas trois pattes à un canard et pas deux pattes

  13. #13
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Citation Envoyé par MacPro Voir le message
    Ma réponse n'a rien d'informatique mais je la donne quand même :

    On dit que ça casse pas trois pattes à un canard et pas deux pattes
    Que ferait-on sans les membres éclairés ?…

    @koala01 Ok, je pense que j'ai à peu près saisi.
    Merci !

  14. #14
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Citation Envoyé par omc24 Voir le message
    Citation Envoyé par Steph_ng8 Voir le message
    Mais je ne vois pas comment l'utiliser en pratique, puisque ton compteur n'est pas accessible.
    Il suffit de rajouter un accesseur
    En fait, ça me paraissait évident ; mais vu que tu ne l'avais pas mis la première fois, je pensais que c'était voulu.

    Citation Envoyé par omc24 Voir le message
    Citation Envoyé par Steph_ng8 Voir le message
    Et que se passe-t-il quand il arrive à 0 ?
    Cela veut dire qu'il n'y à plus d'instance de la classe "A".
    D'accord, ça j'avais compris.
    Je voulais savoir s'il y avait une sorte de traitement automatique, ou s'il fallait s'occuper de la vérification à la main.
    Je suppose que ça reste du manuel…

    Citation Envoyé par omc24 Voir le message
    Citation Envoyé par Steph_ng8 Voir le message
    Ou quand il n'arrive pas 0 à la fin du programme ?
    C'est qu'il y a problème. Tous les objets n'ont pas été détruit. Ou alors, il y a des objets "statiques" qui seront détruit à la sortie du main() et dans ce cas c'est normal.
    C'est bien ce que je me disais.
    Mais dans ce cas, il faut connaître le nombre d'objets statiques de portée globale ou égale à celle du main.
    Bon ok, ce ne doit pas être très compliqué…

Discussions similaires

  1. Réponses: 19
    Dernier message: 29/09/2014, 17h12
  2. Code bizarre avec les pointeurs
    Par deubelte dans le forum C++
    Réponses: 4
    Dernier message: 04/07/2010, 19h08
  3. [Pointeurs et codes [C]]Delaunay et Voronoi
    Par souviron34 dans le forum Contribuez
    Réponses: 1
    Dernier message: 17/02/2009, 09h07
  4. Un code avec pointeurs qui ne marche pas
    Par yohannc dans le forum Débuter
    Réponses: 5
    Dernier message: 31/10/2008, 15h18
  5. Réponses: 1
    Dernier message: 09/07/2006, 23h39

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