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 :

Membre statique, g++ et core dumped


Sujet :

Langage C++

  1. #1
    Membre averti
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juillet 2009
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant Chercheur

    Informations forums :
    Inscription : Juillet 2009
    Messages : 122
    Points : 306
    Points
    306
    Par défaut Membre statique, g++ et core dumped
    Bonjour à tous,

    je suis en train d'essayer de mettre en place une classe d'énumération comme expliquée dans "When enum just isn't enough" et je pense avoir un problème avec l'initialisation d'un membre statique dans une classe template (m_instances dans Enum<T>).

    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
    /* Enum.hpp */
    #ifndef ENUM_HPP
    #define ENUM_HPP
     
    #include <set>
     
    template<typename T>
    class Enum
    {
      protected:
        explicit Enum(int value) : m_value(value) { m_instances.insert(this); }
      public:
        typedef std::set<const Enum<T> *> instances_set;
        int GetValue() const { return m_value; }
      private:
        int m_value;
        static instances_set m_instances;
    };
     
    template<typename T>
    typename Enum<T>::instances_set Enum<T>::m_instances;
     
    #endif
    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
    /* EnumTest.hpp */
    #ifndef ENUMTEST_HPP
    #define ENUMTEST_HPP
     
    #include "Enum.hpp"
     
    class EnumTest : public  Enum<EnumTest>
    {
      private:
        explicit EnumTest(int value) : Enum<EnumTest>(value)  {}
      public:
        static const EnumTest E11;
        static const EnumTest E12;
    };
     
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    /* EnumTest.cpp */
    #include "EnumTest.hpp"
     
    const EnumTest EnumTest::E11(11);
    const EnumTest EnumTest::E12(12);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /* main.cpp */
    #include "EnumTest.hpp"
    #include <iostream>
     
    int main()
    {
      EnumTest e(EnumTest::E11);
      std::cout << "Value of E11 : " << e.GetValue() << std::endl;
      e = EnumTest::E12;
      std::cout << "Value of E12 : " << e.GetValue() << std::endl;
      return 0;
    }
    J'en viens maintenant au problème en lui-même: pour fonctionner, ce bout de code dépend étrangement de l'ordre des fichiers passés au compilateur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ g++ main.cpp EnumTest.cpp
    $ ./a.out
    Value of E11 : 11
    Value of E12 : 12
    $ g++ EnumTest.cpp main.cpp
    $ ./a.out
    Erreur de segmentation (core dumped)
    Bien entendu, je n'aime pas beaucoup que le bon fonctionnement du code dépende de l'ordre de compilation. Si quelqu'un pouvait m'aider à démêler ce problème, je lui en serais reconnaissant

    Bonne journée à tous!

  2. #2
    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,

    En fait c'est "simplement" à cause de ta procédure de compilation...

    Il faut, pour que cela fonctionne correctement :
    1. compiler EnumTest.cpp seul
    2. compiler main.cpp seul
    3. effectuer l'édition de liens des deux fichiers *.o obtenus en [1] et [2]

    Au final, tes commandes devraient ressembler à quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     g++ -c EnumTest.cpp -o EnumTest.o -I.
    g++ -c main.cpp -o main.o -I.
    g+ main.o EnumTest.o
    ./a.out
    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

  3. #3
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Je pense surtout que ça a quelque chose à voir avec un problème sur l'ordre de création des variables statiques (ordre d'évaluation des constructeurs) et sur leur durée de vie.

    La norme C++ est assez stricte la dessus.

    Ceci dit, le code devrait marcher, donc je penche aussi pour un problème sur gcc (enfin, g++).

    C'est peut-être quelque chose à reporter sur leur mailing list, histoire d'avoir une réponse plus claire.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  4. #4
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Je pense surtout que ça a quelque chose à voir avec un problème sur l'ordre de création des variables statiques (ordre d'évaluation des constructeurs) et sur leur durée de vie.

    La norme C++ est assez stricte la dessus.

    Ceci dit, le code devrait marcher, donc je penche aussi pour un problème sur gcc (enfin, g++).

    C'est peut-être quelque chose à reporter sur leur mailing list, histoire d'avoir une réponse plus claire.
    Je ne vois pas de problème dans le comportement de g++. L'initialisation des membres statiques de de spécialisations non explicites de templates de classes est non ordonnée et pour que le code fonctionne, il faudrait que l'intialisation de typename Enum<EnumTest>::instances_set Enum<EnumTest>::m_instances soit ordonnée avant les initialisations de EnumTest::E11 et EnumTest::E12.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  5. #5
    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
    Je ne sais en fait pas si gcc est sensé créer tous les fichiers objets lorsqu'on lui passe une série de fichiers sources...

    Mais, une chose est sure, c'est que si l'on prend effectivement la peine de compiler tous les fichiers les uns après les autres et d'effectuer l'édition de liens sur base des fichiers objets obtenus, il n'y a plus de problème

    Et, ce qui est sur aussi, c'est que, lorsque l'on fournit directement l'ensemble des fichiers source avec la commande indiquée par Meseira, il n'y a aucun fichier objet généré

    De là à dire qu'il y a effectivement un problème dans le pipe de Gcc... Qu'en penses tu
    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

  6. #6
    Membre averti
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juillet 2009
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant Chercheur

    Informations forums :
    Inscription : Juillet 2009
    Messages : 122
    Points : 306
    Points
    306
    Par défaut
    Bonsoir à tous,

    merci pour vos réponses. Si comme le suggère Koala01, il s'agit d'un problème de pipe de g++, alors pourquoi ai-je toujours le même problème avec l'ordre des fichiers dans l'édition des liens?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ g++ -c EnumTest.cpp -o EnumTest.o -I.
    $ g++ -c main.cpp -o main.o -I.
    $ g++ main.o EnumTest.o
    $ ./a.out 
    Value of E11 : 11
    Value of E12 : 12
    $ g++ EnumTest.o main.o
    $ ./a.out 
    Erreur de segmentation (core dumped)
    Si je comprends l'explication de Jean-Marc, le problème viendrait du fait que les deux variables statiques E11 et E12 partagent la même variable statique Enum<EnumTest>::m_instances. Or, rien ne nous assure que l'ordre de création des variables statiques E11, E12 et m_instances se fasse de façon à ce que m_instances soit créée avant E11 et E12. Ai-je bien compris l'explication? Si oui, y a-t-il une manière de gérer cet ordre d'initialisation ou bien est-ce que ce pattern de classe d'énumération est "moisi"?

  7. #7
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Je ne vois pas de problème dans le comportement de g++. L'initialisation des membres statiques de de spécialisations non explicites de templates de classes est non ordonnée et pour que le code fonctionne, il faudrait que l'intialisation de typename Enum<EnumTest>::instances_set Enum<EnumTest>::m_instances soit ordonnée avant les initialisations de EnumTest::E11 et EnumTest::E12.
    Pétard, je ne fais plus assez de C++. Il faut que je remédie à ça...
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  8. #8
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    tu peux utiliser une fonction avec une variable statique dedans, comme il arrive de le voir pour les singletons.

    Regarde dans la faq la section fiasco des statiques et les suivantes.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  9. #9
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Je ne sais en fait pas si gcc est sensé créer tous les fichiers objets lorsqu'on lui passe une série de fichiers sources...
    Oui.

    Mais, une chose est sure, c'est que si l'on prend effectivement la peine de compiler tous les fichiers les uns après les autres et d'effectuer l'édition de liens sur base des fichiers objets obtenus, il n'y a plus de problème
    Non. Ca depend de l'ordre des fichiers dans la ligne de commande, exactement comme quand tu specifies les fichiers .cpp Et si avec des variables globales normales, tu peux eventuellement utiliser le fait que le comportement de gcc et du linker sont definis pour savoir quel ordre utilise, dans le cas des templates, tu ne sais pas avec quel fichier sont associes les membres statiques.

    Et, ce qui est sur aussi, c'est que, lorsque l'on fournit directement l'ensemble des fichiers source avec la commande indiquée par Meseira, il n'y a aucun fichier objet généré
    Si l'executable est genere, je ne vois pas le probleme.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  10. #10
    Membre averti
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juillet 2009
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant Chercheur

    Informations forums :
    Inscription : Juillet 2009
    Messages : 122
    Points : 306
    Points
    306
    Par défaut
    Citation Envoyé par leternel Voir le message
    tu peux utiliser une fonction avec une variable statique dedans, comme il arrive de le voir pour les singletons.
    Merci pour ce conseil, cela règle effectivement le problème. Le fichier Enum.hpp est le seul à changer et devient:
    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
    #ifndef ENUM_HPP
    #define ENUM_HPP
     
    #include <set>
     
    template<typename T>
    class Enum
    {
      protected:
        explicit Enum(int value) : m_value(value) { GetInstSet().insert(this); }
      public:
        typedef std::set<const Enum<T> *> instances_set;
        int GetValue() const { return m_value; }
      private:
        int m_value;
        static instances_set & GetInstSet()
        {
          static instances_set set;
          return set;
        }
    };
     
    #endif
    Ainsi, il n'y a plus la variable statique m_instances qui posait problème dans l'ordre aléatoire d'initialisation:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ g++ main.cpp EnumTest.cpp 
    $ ./a.out 
    Value of E11 : 11
    Value of E12 : 12
    $ g++ EnumTest.cpp main.cpp
    $ ./a.out 
    Value of E11 : 11
    Value of E12 : 12
    Merci pour les commentaires et pour votre aide! Je passe en résolu

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

Discussions similaires

  1. membre statique dans une classe
    Par motrin dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 30/12/2005, 15h15
  2. Problème de Core Dumped !
    Par KneXtasY dans le forum C
    Réponses: 8
    Dernier message: 24/12/2005, 13h11
  3. Segmentation fault (core dumped)
    Par Battosaiii dans le forum C
    Réponses: 13
    Dernier message: 25/11/2005, 18h36
  4. membres statiques
    Par Math75 dans le forum C++
    Réponses: 1
    Dernier message: 17/10/2005, 14h53
  5. Membre statique et DLL
    Par Invité(e) dans le forum Windows
    Réponses: 2
    Dernier message: 15/04/2005, 14h04

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