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 :

[Gestion de la mémoire] Contrôler si un pointeur a été désalloué


Sujet :

C++

  1. #1
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut [Gestion de la mémoire] Contrôler si un pointeur a été désalloué
    Bonsoir,

    Cela fait plusieurs jours que je réfléchis à la façon de coder un système de pointeurs intelligents "maisons", et j'ai enfin fini par l'implémenter. Ce système est très simple, il est de la forme suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    template <typename T>
    class Pointer
    {
    private:
        Object *o;
    public:
        inline Pointer(T* obj) : o(obj) {}
     
        // ...
    };
     
    // Utilisation :
    Pointer<Object> obj = new Object();
    Avec Object = la classe mère de ma bibliothèque.
    Comme tout système de pointeurs intelligents qui se respecte, le mien dispose d'une fonction "IsNull()" qui renvoie true si le pointeur "o" est égal à NULL.

    Le problème : faire un système de pointeurs intelligents pour gérer les pointeurs nuls signifie généralement sortir un bazooka pour tuer une mouche. Ce que je cherche à faire est, à partir de l'adresse du pointeur o, de savoir s'il a été ou non été désalloué par delete.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    inline bool IsNull() const { return (!o || *&o == NULL); }
    Le soucis, logique, est le suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Classe *pointeur = new Classe();
    delete pointeur;
    Après le delete, le pointeur a juste été désalloué, et *&pointeur ne retourne pas NULL mais une valeur belle et bien réelle.

    Ainsi, ce que je cherche à faire est de savoir si le pointeur a ou non été désalloué en se servant de la mémoire. Bien sûr, je vois déjà des réponses du type "pourquoi ne fais-tu pas pointeur = NULL; après le delete ?", ou bien "pourquoi ne pas utiliser les exceptions ?".

    La première solution n'est pas envisageable car ma bibliothèque est déjà bien avancée, et il n'est pas envisageable d'y placer NULL partout où il y a lieu de delete. La seconde n'est pas non plus envisageable car la classe sera très souvent instanciée et utilisée dans le code (pour ne pas dire, toutes les 2 sec 1/4).

    L'unique solution que j'ai trouvée est une solution qui fonction par pointeur sur pointeur. Toutefois, je ne vois pas tellement comment implémenter quelque chose qui tienne la route et qui retourne true si le pointeur a été désalloué et false si le pointeur ne l'a pas été. J'en suis là, mais ça ne fonctionne pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // Ne faites pas attention à la fuite de mémoire...
     
        inline bool IsNull() const {
            if (!o) return true;
            Object *object = o;
            Object **objectP = &object;
            if (*objectP == NULL)
                return true;
            return false;
        }
    Je m'excuse de vous déranger pour ce type de problème, mais de l'aide serait vraiment la bienvenue.

    Merci d'avance à tous ceux qui pourront m'aider,
    Amnell.
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

  2. #2
    Membre averti
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2008
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 227
    Points : 311
    Points
    311
    Par défaut
    Il y a des pistes pour ça dans le Stroustrup

  3. #3
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Salut

    [mode chieur]Pourquoi vouloir coder toi même les pointeurs intelligents ? Il y en a de tout faits dans Boost.[/mode chieur]

    Le principe des pointeurs intelligents est que tu n'as à priori pas à tester si l'objet est détruit ou non, puisqu'il doit l'être automatiquement lorsque le dernier pointeur qui tient l'objet est détruit.

    Après il y a plusieurs méthodes :
    - utiliser un compteur de références (addref/release). Tu as déjà une super class donc ça devrait pas être trop dur.
    - surcharger les opérateurs new, new[], delete et delete[] pour récupérer plus d'infos. Exemple.

    Note que boost a un pointeur intelligent qui te permet d'utiliser ta propre implémentation d'AddRef/Release (intrusive_ptr). Les pointeurs intelligents, ça fait longtemps que du monde se casse les dents dessus, alors il ne faut pas de priver de servir des existants !
    Find me on github

  4. #4
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Bonjour,

    Tout d'abord, merci d'avoir répondu si vite !

    Citation Envoyé par jblecanard Voir le message
    [mode chieur]Pourquoi vouloir coder toi même les pointeurs intelligents ? Il y en a de tout faits dans Boost.[/mode chieur]
    Le problème est que nous sommes plusieurs à travailler sur ce projet de bibliothèque, et nous avons décidé que nous ne toucherions pas à tout ce qui est Boost, Qt, ou autre pour le projet. Nous souhaitons garder un code purement C++. Vous me direz, il existe toujours std::smart_ptr, mais je ne souhaite pas l'utiliser.

    Citation Envoyé par jblecanard Voir le message
    Le principe des pointeurs intelligents est que tu n'as à priori pas à tester si l'objet est détruit ou non, puisqu'il doit l'être automatiquement lorsque le dernier pointeur qui tient l'objet est détruit.
    Oui, à priori. Dans ce cas, pour ce que que je cherche à faire, je ne sais pas vraiment s'il faut parler de pointeurs intelligents, car je ne fais qu'englober un pointeur dans le cadre d'une fonction pour éviter des segfaults dues à un accès concourant/pointeur désalloué/pointeur null/autre. Le pointeur ne doit en aucun cas être détruit par la destruction de l'instance de la classe de pointeur intelligent, dans le cadre de ce que je cherche à faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void DoSomething(Object *obj) {
        Pointer<Object> object = obj;
        if (!obj.IsNull()) {
            // On manipule l'objet.
        }
        else {
            // On fait autre chose.
        }
    }
    À savoir que par threading, "obj" pourrait très bien avoir été supprimé par delete (!= NULL, donc), d'où le problème du topic.

    Citation Envoyé par jblecanard Voir le message
    Après il y a plusieurs méthodes :
    - utiliser un compteur de références (addref/release). Tu as déjà une super class donc ça devrait pas être trop dur.
    - surcharger les opérateurs new, new[], delete et delete[] pour récupérer plus d'infos. Exemple.
    La deuxième solution semble à écarter, puisque je n'ai "pas le droit" de modifier la classe Object et ses sous-classes. Si je pouvais, ç'aurait été très simple : surcharge de l'opérateur delete avec assignation de NULL et l'affaire est réglée.

    Toutefois, pour la première, nous retombons sur le problème initial : comme le pointeur intelligent ne détruit pas le pointeur, il ne lui affecte pas NULL, donc on ne peut pas savoir si le pointeur est désalloué ou pas, lorsque l'on gère le compteur de références. Je peux bien sûr me tromper sur ce point.
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

  5. #5
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par Amnell Voir le message
    Le problème est que nous sommes plusieurs à travailler sur ce projet de bibliothèque, et nous avons décidé que nous ne toucherions pas à tout ce qui est Boost, Qt, ou autre pour le projet. Nous souhaitons garder un code purement C++.
    Clair que Boost est écrit en ADA orientée agents ...
    Reinventer la roue pour le plaisir est un plaisir de masochiste.

    Entre un truc fait main et un truc open source moultement testé et réputé pour être l'antichambre de la STL ... bref.

  6. #6
    Membre éprouvé 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 : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Bonjour,

    J'ai du mal à voir l'intérêt de développer une classe de « pointeurs intelligents » juste pour vérifier qu'un pointeur n'a pas été désalloué.
    D'ailleurs, si c'était possible, cette fonctionnalité serait disponible directement en C, et ce serait un point mis en avant pour la gestion de la mémoire en C, non ?

    Alors si vous voulez absolument être sûrs que vos pointeurs sont valides, ce serait certainement mieux d'utiliser des « pointeurs intelligents » dans leur véritable but, à savoir gérer de manière transparente la mémoire, quitte à créer votre propre classe, et ne plus utiliser de pointeurs nus.
    Mais dans ce cas, vous devrez repasser en revue tout votre code, c'est vrai…

    À vous de voir quel est le moindre mal…

  7. #7
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par Amnell Voir le message
    La deuxième solution semble à écarter, puisque je n'ai "pas le droit" de modifier la classe Object et ses sous-classes. Si je pouvais, ç'aurait été très simple : surcharge de l'opérateur delete avec assignation de NULL et l'affaire est réglée.
    Dans les deux cas, la super classe sera impactée. Quoique dans le second, tu peux surcharger tous les "delete" et pas seulement ceux de la super classe.

    Le problème là est que tu veux faire quelque chose de difficile, mais que tu ne t'en donne pas les moyens :
    - Pas de boost
    - Pas touche à la super classe (c'est bête c'est tout l'intérêt d'une super classe !)
    - Pas touche aux opérateurs...

    Il n'y a pas de formule magique, si tu veux y arriver, il va falloir toucher à quelque chose.

    La seule chose que je vois avec tes contraintes, c'est loguer les appels à delete avec la valeur du pointeur et un define. Voici une technique pour le faire :

    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
    #include <iostream>
     
    class Effaceur
    {
    public:
    	virtual ~Effaceur () { }
     
    	static Effaceur& GetInstance()
    	{
    		static Effaceur instance;
    		return instance;
    	}
     
    	void effacer(void* iPtr)
    	{
    		delete iPtr;
    		std::cout << "Omagad le pointeur " << iPtr << " a été effacé" << std::endl;
    	}
     
    void	operator << (void* iPtr)
    	{
    		effacer(iPtr);
    	}
     
    private:
    	Effaceur(){};
     
    };
     
    class Objet {};
     
    #define delete Effaceur::GetInstance() << 
     
    int main() {
    	Objet * a = new Objet();
    	delete a;
    	return 0;
    }
    Mais ça t'oblige à conserver une liste des objets détruits, ce qui est très bof. Et il ne faut pas oublier de ruser pour delete[] (même technique avec un "EffaceurTableau" par exemple).

    Note que tu peux très bien définir une surcharge des opérateurs en debug pour tester et la virer dans la release.

    Au fait, es tu bien sûr que la combinaison de shared_ptr et de weak_ptr ne te conviendrais pas ? weak_ptr fait ce que tu recherches, pour peu qu'on l'utilise de manière cohérente avec shared_ptr.
    Find me on github

  8. #8
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    @Joel F > Je suis bien d'accord, mais pour le coup, je ne peux pas faire autrement, donc la question ne se pose pas.
    @Steph_ng8 > Ce qui reste en réalité une des rares solutions, puisque sans cela, je me retrouverais avec un truc hardcodé.
    @jblecanard > Je vais regarder cela, merci bien.

    Merci à vous pour vos réponses, j'ai désormais suffisamment d'éléments pour terminer.
    Je passe donc le topic en résolu.

    Bonne continuation,
    Amnell.
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

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

Discussions similaires

  1. Problème de pointeurs et de gestion de la mémoire
    Par remixtech dans le forum Débuter
    Réponses: 1
    Dernier message: 27/06/2008, 21h20
  2. Réponses: 17
    Dernier message: 02/02/2006, 12h03
  3. [Info][Mémoire] utilisée pour un pointeur null
    Par thomas_strass dans le forum Langage
    Réponses: 14
    Dernier message: 04/11/2004, 12h48
  4. Gestion de la mémoire entre plusieurs DLL
    Par Laurent Gomila dans le forum C++
    Réponses: 7
    Dernier message: 27/07/2004, 15h28
  5. Gestion des variables - mémoire ?
    Par RIVOLLET dans le forum Langage
    Réponses: 4
    Dernier message: 26/10/2002, 12h44

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