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

Langage C++ Discussion :

problème lecture variable static d'un singleton


Sujet :

Langage C++

  1. #1
    Nouveau membre du Club
    Inscrit en
    Avril 2007
    Messages
    74
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 74
    Points : 33
    Points
    33
    Par défaut problème lecture variable static d'un singleton
    Bonjour,

    Je rencontre un problème pour lire une variable statique de ma classe singleton "model".
    En effet dans cette classe, je declare:

    .h:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public:
    static int maVariable;
    int getVariable()
    void setVariable(int *p_varaible)
    .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
    16
    17
    18
    19
    20
    21
     
    int maVariable;
     
    int model::getVariable()
    {
       return maVariable;
    }
     
    void model::setVariable(int *p_varaible)
    {
       maVariable = *p_variable;
    }
     
    model* model::getInstance()
    {
    	if ( NULL == instance )
    	{
    		instance =  new model();
    	}
    	return instance;
    };
    Jusque la, aucun problème. Mon constructeur et destructeur sont bien privé et mon instance n'est créée qu une seule fois (principe du singleton).

    Le problème est lors de l'accès à ma variable. Lorsque j'initialise ma variable dans une classe donnée et que je lis cette même variable dans la même classe, aucun problème. Le problème est lorsque je veux relire la variable initialisée dans la classe précédente dans une autre classe, model::getVariable() retourne "0". Je recupère bien l'instance avant d'accéder à ma variable dans l'autre classe avec getInstance().

    J'ai essayé avec une variable "en dur" dans ma classe et pas de problème (ce qui est normale).

    Je veux accéder à cette variable dans n'importe quelle classe de mon projet d'où cette question:

    Le singleton est il bien fait pour ce type de problème?

    Est il préférable d'utiliser un segment commun (dataseg) pour ce type de problème?

    D'où pourrait venir le problème?

    Je vous remercie.

  2. #2
    Membre émérite
    Avatar de ymoreau
    Homme Profil pro
    Ingénieur étude et développement
    Inscrit en
    Septembre 2005
    Messages
    1 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur étude et développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 154
    Points : 2 834
    Points
    2 834
    Par défaut
    Je ne vois pas où serait le problème désolé.

    Par contre, petite critique : l'idée d'un objet singleton est qu'il soit instancié une seule fois et qu'il soit accessible de n'importe grâce à la fonction statique getInstance(). Du coup on a bien une instance de classe (même si elle est unique), alors que tu utilises une variable statique pour maVariable, puisque ta classe est instanciée tu devrais utiliser une donnée membre normale et pas statique.

    Edit : je viens de voir que tu redéclares ta variable maVariable dans ton .cpp ! J'imagine que tu voulais l'initialiser, mais pour bien faire appel à ta donnée membre statique il faut préciser qu'elle vient de ta classe. Tel qu'il est ton code déclare une variable globale au .cpp qui porte le même nom que ta variable de classe, il est probable qu'il y ait confusion.
    Tu devrais mettre dans .cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int model::maVariable = 0;
    Mais je pense quand même qu'il vaut mieux utiliser une donnée membre normale plutôt que statique, que tu initialiserais dans ton constructeur.

  3. #3
    Nouveau membre du Club
    Inscrit en
    Avril 2007
    Messages
    74
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 74
    Points : 33
    Points
    33
    Par défaut
    Citation Envoyé par YoniBlond Voir le message
    Edit : je viens de voir que tu redéclares ta variable maVariable dans ton .cpp ! J'imagine que tu voulais l'initialiser, mais pour bien faire appel à ta donnée membre statique il faut préciser qu'elle vient de ta classe. Tel qu'il est ton code déclare une variable globale au .cpp qui porte le même nom que ta variable de classe, il est probable qu'il y ait confusion.
    Tu devrais mettre dans .cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int model::maVariable = 0;
    Merci,

    Petite erreur de frappe, je déclare bien ma variable de cette façon.
    Je vai voir ce que ça donne en la passant en membre normal plutot que statique.

  4. #4
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Pourquoi ne pas tirer profit des références et utiliser le const :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int getVariable() const;
    void setVariable(int const &r_varaible);
    model& getInstance();

  5. #5
    Nouveau membre du Club
    Inscrit en
    Avril 2007
    Messages
    74
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 74
    Points : 33
    Points
    33
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Salut,
    Pourquoi ne pas tirer profit des références et utiliser le const :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int getVariable() const;
    void setVariable(int const &r_varaible);
    model& getInstance();
    J'ai essayé quelque chose comme ça mais sans effet. Je retest ça dès que possible. Merci.

  6. #6
    Nouveau membre du Club
    Inscrit en
    Avril 2007
    Messages
    74
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 74
    Points : 33
    Points
    33
    Par défaut
    J'ai retravailler sur ce problème. Le problème viens du fait que je fais appel au singleton dans des process différent d'ou le problème d'accès à la variable puisque les process ont chacun leur propre zone mémoire.

    Etes vous d'accord?

    Si oui on peut dire que le problème au résolu. Je vais partager une zone mémoire pour resoudre le problème.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Le problème vient bien plus certainement du fait que tu utilise un singleton (ou la variable statique que tu veux rendre membre de ce singleton) là où ce n'est pas forcément nécessaire.

    Le pattern singleton a en effet pour objectif de s'assurer qu'il n'existe jamais qu'une instance d'un objet particulier.

    Par extension, il est donc normal que chaque membre de cet objet particulier n'existe jamais... qu'une seule et unique fois (dans l'instance unique de cet objet)

    Une variable statique est ce que l'on appelle en conception une variable de classe (par opposition à une variable d'instance) et est "partagée" entre les différentes instances d'objet de même type.

    Mais à l'utilisation, on va donc se baser sur le fait qu'il y a potentiellement plusieurs instances de l'objet qui peuvent exister en même temps (ce qui n'est pas le cas d'un singleton )

    L'idée est donc:

    Soit de créer un singleton avec, selon la manière dont tu l'implémente, une ou maximum deux fonctions statique, sous 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
    class Singleton
    {
        public:
            static Singleton& instance()
            {
                 /* l'instance sera partagée par tous les appels à 
                  * la fonction statique instance
                  */
                 static Singleton s;
                 return s;
            }
            /* les autres fonctions membres ne sont pas statiques */
            void setValue(int v){m_val=v;}
            int value()const {return m_val;}
        private:
            /* on empêche l'accès "depuis l'extérieur" au constructeur
             * et au destructeur
             */
           Singleton():m_val(0){}
           ~Singleton(){}
           /* et on interdit la copie et l'assignation (le constructeur
            * par copie et l'opérateur d'affectation sont déclarés mais non
            * implémentés
            */
          Singleton(Singleton const &);
          Singleton& operator=(Singleton);
          int m_val;
    };
    qui sera utilisé sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    int main()
    {
        Singleton::instance().setValue(5);
        /*...*/
        return 0;
    }
    /* l'instance sera détruite en sortie du programme */
    ou de (utile dans certains cas)
    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
    class Singleton
    {
        public:
            static Singleton& instance()
            {
                 if(!inst)
                     inst=new Singleton;
                 return *inst;
            }
            static void destroy()
            {
                delete s;
                s=NULL;
            }
            /* les autres fonctions membres ne sont pas statiques */
            void setValue(int v){m_val=v;}
            int value()const {return m_val;}
        private:
            /* on empêche l'accès "depuis l'extérieur" au constructeur
             * et au destructeur
             */
           Singleton():m_val(0){}
           ~Singleton(){}
           /* et on interdit la copie et l'assignation (le constructeur
            * par copie et l'opérateur d'affectation sont déclarés mais non
            * implémentés
            */
          Singleton(Singleton const &);
          Singleton& operator=(Singleton);
          int m_val;
          /* nous avons un pointeur statique vers l'instance */
          Singleton * inst;
    };
    /* dans le fichier *.cpp correspondant: */
    Singleton * Singleton::inst=NULL;
    qui sera utilisée sous 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
    int main()
    {
        Singleton::instance().setValue();
        /*...*/
        /* nous forçons la libération de l'instance avant de quitter le programme
         * !!! ATTENTION: si tu le fait ailleurs dans le programme, tu
         * obtiendra une nouvelle instance au prochain appel de la fonction
         * instance() (toutes les modifications apportées au singleton 
         *avant l'appel de destroy() seront perdues)
         */
        Singleton::destroy();
        return 0;
    }
    Soit, tu veux qu'une variable particulière soit partagées par les différentes instances d'un même objet (auquel cas, il est souvent intéressant d'envisager qu'il s'agisse en réalité d'une constante) et tu travailles sous 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
     
    class MaClass
    {
        public:
            /* si nous déclarons ces fonctions statiques, il sera possible
             * de les appeler sans disposer d'une instance particulière
             * de MaClass
             */
           /*static */ void setStaticValue(int v){m_value=v;}
           /*static */ int staticValue() const{return m_value;}
        private:
            static int m_value;
    };
    /* dans le *.cpp correspondant */
    int MaStruct::m_value = 0;
    utilisée sous 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
    int main()
    {
        MaClass c1;
        MaClass c2;
        /* on peut modifier la valeur au départ de c2 et
         * la récupérer au départ de c1 (mais n'est ce pas un peu
         * dangereux ??)
         */
        c2.setStaticValue(10);
        std::cout<<c1.staticValue()<<std::endl;
        /*...*/ 
        /* si !!! et seulement si !!! setStaticValue() et staticValue() sont 
         * déclarées statiques, ceci fonctionne également 
         */
        MaClass::setStaticValue(45);
        std::cout<<MaClass::staticValue()<<std::endl;
        return 0;
    }
    Soit, comme je te l'ai dit, on envisage le fait qu'il s'agisse d'une valeur constante, et nous pouvons donc avoir "simplement" un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class MaClass
    {
        public:
            /* Comme elle est déclarée constante, on peut la laisser visible
             * depuis l'extérieur ;) 
             */
           static int const value;
    };
    /* et dans le *.cpp correspondant */
    int const MaClass::value = 10;
    qui sera utilisée sous 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
    int main()
    {
        /* on n'a pas besoin d'une instance de MaClass pour accéder à la valeur
         */
        std::cout<<MaClass::value<<std::endl;
        /* mais rien n'empêche d'y accéder depuis une instance donnée */
        MaClass c1;
        int i;
        /*...*/
        if(i<c1.value)
            std::cout<<"plus petit "<<std::endl;
        else
            std::cout<<"plus grand ou egal"<<std::endl;
        return 0;
    }
    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
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    J'ai bien peur qu'il ne parle de partager un singleton dans une librairie (DLL ou non) "partagée" par deux processus distincts.

    Si il ya deux processus, il y a deux espaces mémoire, et donc... deux instances distinctes du singleton.

    Le partage d'une zone mémoire n'est que rarement une bonne solution (d'autant qu'elle est difficile à mettre en oeuvre). Quel est le but ultime (si ce n'est pas indiscret) ?
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  9. #9
    Nouveau membre du Club
    Inscrit en
    Avril 2007
    Messages
    74
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 74
    Points : 33
    Points
    33
    Par défaut
    Citation Envoyé par nicroman Voir le message
    J'ai bien peur qu'il ne parle de partager un singleton dans une librairie (DLL ou non) "partagée" par deux processus distincts.

    Si il ya deux processus, il y a deux espaces mémoire, et donc... deux instances distinctes du singleton.

    Le partage d'une zone mémoire n'est que rarement une bonne solution (d'autant qu'elle est difficile à mettre en oeuvre). Quel est le but ultime (si ce n'est pas indiscret) ?
    C'est exactement ça mon problème. J'ai plusieurs processus qui font appelle à la même DLL. Le problème est que dans cette DLL, j'utilise une fonction d'initialisation au début de mon application pour initialiser certaine variable dont j'aurais besoin pour la suite. Je stocke donc cette variable dans un singleton pour la réutiliser par la suite. Le problème est que j'y accède dans le processus qui initialise mes variables mais pas dans mes autres processus du fait que les espaces mémoires sont distincts.

    C'est pour cela que je pensais à une zone de mémoire partagée entre touts mes processus (via un dataseg, assez facile à mettre en oeuvre) même si c'est un peu "barbare".

    Auriez vous une autre solution plus "propre" pour resoudre ce problème"?

    Je vous remercie.

Discussions similaires

  1. Singleton ou variables statics """global""" ?
    Par base-un dans le forum Langage
    Réponses: 16
    Dernier message: 27/11/2010, 04h10
  2. [Singleton] question sur variable static
    Par ultimax dans le forum Langage
    Réponses: 6
    Dernier message: 13/01/2010, 11h43
  3. Problème avec une variable static
    Par Kevin12 dans le forum Général Java
    Réponses: 2
    Dernier message: 05/05/2008, 17h20
  4. Problème de variable en lecture XML en AS2.0
    Par blanchonvincent dans le forum ActionScript 1 & ActionScript 2
    Réponses: 4
    Dernier message: 17/01/2008, 20h33
  5. Réponses: 6
    Dernier message: 12/09/2007, 17h31

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