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 :

Différencier les pointeurs de variable dynamique des autre pointeurs


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Ekinoks
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2003
    Messages
    687
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2003
    Messages : 687
    Par défaut Différencier les pointeurs de variable dynamique des autre pointeurs
    Salut !

    J'essaye de trouver un moyen de différencier un pointeur vers une variable allouer dynamiquement des autre pointeurs, pour pouvoir effectuer un delete si il a était créé dynamiquement, et ne rien faire si il n'a pas était créé dynamiquement.

    La mémoire d'un programme C semble être gérer de cette manière :
    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
     
    ________________
    |                |
    | VARIABLE LOCAL |
    |      (pile)    |
    |________________|
    |       | |      |
    |        V       |
    |                |
    |      FREE      |
    |                |
    |       ^        |
    |______| |_______|
    |                |
    | ALLOCATION     |
    |      (tas)     |
    |________________|
    |                |
    | VARIABLE STATIC|
    | (segment data) |
    |________________|
    |                |
    | VARIABLE GLOBAL|
    |  (segment bss) |
    |________________|
    |                |
    | FONCTION       |
    | (segment text) |
    |________________|
    Une solution consisterais donc à vérifier que la valeur du pointeur soit compris entre le pointeur la dernière variable static et le pointeur la dernière variable local.


    Pour récupérer la dernière valeur de la variable local, c'est pas bien compliquer.
    Par contre, pour arriver à récupérer la valeur de la dernière variable static (ou la première variable dynamique) c'est plus compliqué (surtout si on a plusieurs fichier sources).

    Avez-vous une idée de comment faire ?

    Ou peu être une autre méthode plus simple ?

    Merci pour votre aide.

  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
    Cela n'est absolument pas fiable.
    La seule chose que tu peux faire, c'est remplacer les pointeurs "bètes" par des pointeurs intelligents qui mémorisent le truc (possible facilement en C++, mais impossible de faire un truc vraiment pratique en C).

    Pour les objets alloués sur le tas, tu peux même ajouter un comptage de références (qui peut même être un comptage intrusif si tu aménages exprès l'allocateur).
    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 chevronné
    Avatar de NewbiZ
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2002
    Messages
    184
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2002
    Messages : 184
    Par défaut
    Ca a déjà été abordé maintes et maintes fois sur comp.lang.c++, et effectivement la seule solution potable est celle que tu cites. Le seul défaut serait que c'est intrinsèquement sujet à nombre de problèmes de portabilité.

    Comme dit par Médinoc, pourquoi vouloir éloigner autant la logique de destruction des variables? Les smart pointers résolvent bien ce problème.

    Le plus propre serait encore de se pencher sur les différentes bibliothèques de reflection pour C++, qui se proposent d'ajouter tout un tas de métapropriétés aux variables.

  4. #4
    Membre chevronné Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Par défaut
    Le plus propre serait encore de se pencher sur les différentes bibliothèques de reflection pour C++, qui se proposent d'ajouter tout un tas de métapropriétés aux variables.
    Je serai bien intéressé par ce type de bib. si tu avais des noms...
    Merci

  5. #5
    Membre éclairé Avatar de Ekinoks
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2003
    Messages
    687
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2003
    Messages : 687
    Par défaut
    Merci pour vos réponses


    Désolé de répondre plusieurs jour après vos réponses, mais c'est que je voulais bien étudier les solutions que vous m'avez proposé avant ^^;

    Donc, j'ai réfléchie pour me créer des pointeurs intelligents et ca résous effectivement un bon nombre de petit désagrément comme empêcher de déallouer un objet déjà déallouer...

    Par contre le problème de la différenciation entre les pointeurs de variable dynamique des autre pointeurs persiste toujours.

    Voici un petit exemple en utilisant mon nouveau pointeur intelligent ^^
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    int main()
    {
       Ptr<Object> p;
       p = new Object(); 
       p.destroy();           // l'objet est déalouer sans poser de problème.
     
       Object o;
       p = &o;
       p.destroy();   // AIE !! Erreur ! :'(
     
       return 0;
    }

    A la limite une solution serais d'obliger de créer des instance d'Object avec new comme ca :
    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
     
    class Object
    {
       Object(){}
       public :
          static Object* new_Object(){*return new Object(); }
    }
     
    int main()
    {
       Ptr<Object> p;
       p = Object::new_Object(); 
       p.destroy();           // l'objet est déalouer sans poser de problème.
     
       Object o;   // cool, ca bloque à la compilation ! =)
       p = &o;
       p.destroy();
     
       return 0;
    }
    Le problème est que le code devient plus lourd et moins intuitif non ?

    Donc pour résumer, pour empécher que l'erreur de mon premier exemple est lieu il y a deux solution :
    1> A l'execution : Le pointeur intelligent arrive à faire la différence entre un pointeur "délétable" et un pointeur non "délétable"
    2> A la compilation : On génère une erreur à la compilation si on donne un pointeur non "délétable" au pointeur intelligent (ce que j'essaye de faire indirectement en obligent d'utiliser "new")


    Pour la solution numéro (1), je ne vois pas comment faire (si ce n'est en comparent valeur du pointeur pour arriver à déterminer dans quel segment il se trouve mais comme vous l'avez souligné c'est pas portable et pas fiable)
    Pour la solution numéro (2), il y a bien la solution que je propose dans mon second exemple, mais elle ne me semble pas très propre et pas suffisamment intuitif à utiliser.


    Savez vous comment implémenter proprement la solution 1 ou 2 ? ou peu être avez vous d'autre idée ?

    Merci pour votre aide.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    L'idéal est quand même toujours de partager les responsabilités.

    Ainsi, de prime abord, je vois principalement deux raisons d'utiliser des pointeurs:

    La première, c'est de fournir une référence à un objet qui se trouve ailleurs, et la seconde est de permettre un mécanisme de polymorphisme.

    Dans le premier cas, tu peux très bien avoir un conteneur "séparé" d'objets non alloués de manière dynamiques auquel font référence tous les pointeurs.

    Lors de l'utilisation du pointeur, tu n'a alors qu'à t'inquiéter d'utiliser le pointeur, mais c'est le conteneur qui doit décider d'en créer de nouveaux ou d'en supprimer. (il faut, bien sûr, prévoir d'indiquer aux éléments externes qui utilisent les pointeurs quand ils deviennent invalide du fait de la destruction de l'objet sur lequel ils pointent).
    Cela pourrait prendre une forme proche de
    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
    60
    61
    62
    63
    64
    65
    66
    class Mediator;
    class Controlee;
    class Object
    {
        /* le type d'objet que tu veux utiliser */
    };
    class Conteneur // éventuellement sous la forme d'un singleton ou 
                    // contenu dans un élément plus global ;)
    {
        public:
            Conteneur(Mediator* media):media(media),tab()
            createObject(/*parametre nécessaires à la création d'un objet*/)
            {
                tab.push_back(Object(/*paramètres*/));
            }
            Objet* operator[](size_t ind)
            {
                 return &tab[ind];
            }
            removeObject(size_t ind)
            {
                 media->remove(&tab[ind]);
                 tab.erase(ind);
            }
        private:
            Mediator * media;
            std::vector<Object> tab;
    };
    class Mediator // sans doute aussi un singleton, ou contenu dans une 
                   // structure plus globale
    {
        public:
            Mediator():tab(){}
            ~Mediator(){}
            Controlee& operator[](size_t ind)
            {
                return tab[ind];
            }
            void addControlee(Object * ptr)
            {
                tab.push_back(Controlee(ptr));
            }
            void remove(Object* ptr)
            {
                tab.erase(tab.removeif(tab.begin(), tab.end(),Controlee.equal(ptr)),
                              tab.end());
            }
        private:
            std::vector<Controlee> tab;
    };
    class Controlee
    {
        public:
            Controlee(Object* ptr):ptr(ptr){}
            ~Controlee(){}
            friend class equal;
            class equal
            {
                 bool operator()(const Controlee& c1, const Controlee& c2)
                 {
                     return c1.ptr==c2.ptr;
                 }
            }
        private:
            Object* ptr;
    };
    (il reste sans doute une ou l'autre erreur... mais je n'ai pas encore dormi )

    Dans le deuxième cas, cela passera par une allocation dynamique de la mémoire, et, fatalement, par une libération de cette mémoire lorsque l'objet doit être détruit.

    Mais, quoi qu'il en soit, ce sera toujours au conteneur de décider de l'allocation et de la libération des pointeurs

    En tout état de cause, si tu en viens à vouloir mélanger les pointeurs statiques et les pointeurs dynamiques dans un même conteneur, tu peux réellement te dire qu'il y a sans doute comme un problème de conception quelque part
    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

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 16/07/2013, 17h57
  2. Réponses: 2
    Dernier message: 23/09/2009, 15h40
  3. Ajout d'une variable dynamique de type pointeur
    Par mmooaa dans le forum Langage
    Réponses: 3
    Dernier message: 02/01/2007, 23h04
  4. Réponses: 2
    Dernier message: 19/07/2006, 00h12
  5. Réponses: 16
    Dernier message: 27/05/2006, 08h40

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