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 :

Comportement erratique en héritage


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    230
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 230
    Points : 132
    Points
    132
    Par défaut Comportement erratique en héritage
    Bonjour à tous, mon problème a certainement été évoqué mais tous mes axes de recherche mènent à des recherches infructueuses...

    Le voici donc :
    J'ai développé 2 classes dont une qui est la fille de l'autre

    headers :
    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 Parent {
    int val;
     
    Parent();
    virtual ~Parent();
    void start(void);
    virtual void run(void);
    }
     
    class Enfant : Parent {
    Enfant();
    virtual ~Enfant();
    void run(void);
    }
    implémentation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Parent::Parent() { }
    Parent::~Parent() { }
    void Parent::start() {
    boost::thread(boost::bind(&Parent::run, this));
    }
    void Parent::run() { std::cout << "problème" << std::endl; }
     
    Enfant::Enfant() { }
    Enfant::~Enfant() { }
    void Enfant::run() { std::cout << "Ok" << std::endl; }
    voici mon main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    main() {
    Enfant enfant;
    enfant.start();
    }
    Vous l'avez compris je devrais avoir dans 100% des cas :
    "Ok"

    Malheureusement en réalité je n'ai ce résultat que dans 90% des cas environ. Parfois il m'affiche "Problème", ce qui signifie que la méthode run() du parent a été appelée...
    J'en déduis que l'appel a start a été effectué dans le parent et éventuellement que l'enfant n'a même pas été complètement instancié.
    Que dois-je en conclure ? Est-ce un problème conceptuel ou bien d'implémentation ? Est-ce une particularité de boost::thread que je n'aurais pas pris en compte ?

    Merci pour votre aide
    Tristan

  2. #2
    Membre averti Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Points : 323
    Points
    323
    Par défaut
    Bonjour,
    Il est clair que ce code n'est pas celui que vous utilisez vraiment(il n'est pas compilable) donc je ne peut que faire des suppositions.
    En générale ce genre de problème est lié a du "slicing". C'est ce qui arrive quand on copie un objet enfant dans un objet ancêtre. Par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Enfant enfant;
    Parent parent = enfant; //Et la, c'est le drame
    parent.start();
    Le plus simple pour éviter a coup sur ce genre d’erreur, c'est de rendre les class de base non copiable:
    - En déclarant le constructeur par copie et l'operateur = en privé(sans les implémenter)
    - Ou en héritant de boost::noncopyable

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    230
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 230
    Points : 132
    Points
    132
    Par défaut
    Bonjour

    merci pour ta réponse !
    C'est vrai que je n'ai pas mis le code original mais une version un peu allégée...

    J'ai opéré les modifications proposées en faisant hériter ma classe de boost::noncopyable et j'ai toujours les mêmes comportements...

    Cdlt

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    230
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 230
    Points : 132
    Points
    132
    Par défaut
    Allez voici le code ça sera plus facile pour décrypter le problème !

    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
     
    /* 
     * File:   OPThread.h
     * Author: tristan
     *
     * Created on 29 juin 2011, 22:05
     */
     
    #ifndef OPTHREAD_H
    #define	OPTHREAD_H
     
    #include <boost/shared_ptr.hpp>
    #include <boost/thread.hpp>
    #include <boost/function.hpp>
    #include <boost/noncopyable.hpp>
     
    #include "opus/flow/Threadable.h"
     
    namespace opus {
        namespace flow {
     
            class OPThread : boost::noncopyable {       
            protected:            
                bool running_;
                bool shouldStop_;
                boost::shared_ptr<boost::thread> thread_;            
     
            public:                 
                OPThread();
                virtual ~OPThread();
                void start();
                void stop(void);
                bool isRunning(void);
                void join(void); 
                void timed_join(time_t millis); 
                bool shouldStop(void);
                void sleep(unsigned int millis);            
     
            protected:
                void _start(void);
                virtual void run(void);            
            };
            typedef boost::shared_ptr<OPThread> OPThreadPtr;
        }
    }
     
    #endif	/* OPTHREAD_H */
    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
     
    #include <iostream>
    #include <boost/thread.hpp>
     
    #include "OPThread.h"
    #include "opus/Logger.h"
    #include "opus/system/System.hpp"
     
    namespace opus {
        namespace flow {
     
            OPThread::OPThread() {
                this->running_ = false;
                this->shouldStop_ = false;
            }
     
            OPThread::~OPThread() {
     
            }
     
            void OPThread::start() {
                if (!(this->running_) && !(this->shouldStop_)) {
                    this->thread_ = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&OPThread::run, this)));    
                }
            }
     
            void OPThread::stop(void) {
                if ((this->running_) && (!this->shouldStop_)) {
                    this->shouldStop_ = true;
                }
            }
     
            bool OPThread::isRunning(void) {
                if(this->thread_)
                    return this->running_;
                else
                    return false;
            }
     
            void OPThread::join() {
                if(this->thread_)
                    this->thread_->join();
            }
     
            void OPThread::timed_join(time_t millis) {
                if(this->thread_)
                    this->thread_->timed_join(boost::posix_time::milliseconds(millis));
            }
     
            void OPThread::run() {
                opus::Logger logger = opus::Logger::getInstance();
                logger.error("This thread class does not have a run method !");
            }
     
            bool OPThread::shouldStop() {
                return this->shouldStop_;
            }
     
            void OPThread::sleep(unsigned int millis) {
                opus::system::sleepInterruptible(millis, boost::bind(&OPThread::shouldStop, this), 100);
            }
        }
    }
    La classe enfant (c'est un test unitaire) :
    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
     
    #define TEST_VAL 28
    class ThreadTest : public opus::flow::OPThread {
        //friend class opus::flow::OPThread;
        int val;
        bool inf;
    public:
        ThreadTest(bool infinite = false) { 
            val = 0; 
            inf = infinite; 
        };
        virtual ~ThreadTest() { };
        int getVal() { return val; };    
     
        void run() {        
            if(!inf) {
                for(int i = 0 ; i < TEST_VAL ; i++) {
                    val += 1;
                }
            } else {
                while(!shouldStop_) {
                    val += 1;
                    this->sleep(1000);
                }
            }
        };
    };
    typedef boost::shared_ptr<ThreadTest> ThreadTestPtr;
    Et l'appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     ThreadTestPtr th1(new ThreadTest(true));
            ThreadTestPtr th2(new ThreadTest(true));
            ThreadTestPtr th3(new ThreadTest(true));
            ThreadTestPtr th4(new ThreadTest(true));
     
            th1->start();
            th2->start();
            th3->start();
            th4->start();
    Le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    ERROR - 20110701105954 - This thread class does not have a run method !
    ERROR - 20110701105954 - This thread class does not have a run method !
    ERROR - 20110701105954 - This thread class does not have a run method !
    ERROR - 20110701105954 - This thread class does not have a run method !
    ERROR - 20110701105954 - This thread class does not have a run method !
    ERROR - 20110701105955 - This thread class does not have a run method !
    ERROR - 20110701105955 - This thread class does not have a run method !
    Segmentation fault: 11
     : OK
    L'exception dans le détail :
    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
     
    Program received signal EXC_BAD_ACCESS, Could not access memory.
    Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
    0x0000000000000000 in ?? ()
     
    #0  0x0000000000000000 in ?? ()
    #1  0x0000000100071c19 in atomic_exchange_and_add [inlined] () at :145
    #2  0x0000000100071c19 in boost::detail::sp_counted_base::weak_release () at :157
    #3  0x0000000100071c19 in boost::detail::shared_count::~shared_count (this=<value temporarily unavailable, due to optimizations>) at sp_counted_base_gcc_x86.hpp:146
    #4  0x000000010003b947 in boost::shared_ptr<boost::thread>::~shared_ptr (this=0x100500420) at shared_ptr.hpp:169
    #5  0x000000010003ae74 in opus::flow::OPThread::~OPThread (this=0x100500410) at OPThread.cpp:18
    #6  0x0000000100022884 in ThreadTest::~ThreadTest (this=0x100500410) at newtestclass8.h:26
    #7  0x00000001000044ba in boost::checked_delete<ThreadTest> (x=0x100500410) at checked_delete.hpp:34
    #8  0x0000000100004466 in boost::detail::sp_counted_impl_p<ThreadTest>::dispose (this=0x100500440) at sp_counted_impl.hpp:78
    #9  0x0000000100071c19 in atomic_exchange_and_add [inlined] () at :145
    #10 0x0000000100071c19 in boost::detail::sp_counted_base::weak_release () at :157
    #11 0x0000000100071c19 in boost::detail::shared_count::~shared_count (this=<value temporarily unavailable, due to optimizations>) at sp_counted_base_gcc_x86.hpp:146
    #12 0x000000010000323d in boost::shared_ptr<ThreadTest>::~shared_ptr (this=0x7fff5fbff270) at shared_ptr.hpp:169
    #13 0x0000000100002258 in newtestclass8::testMultiple (this=0x100414aa0) at newtestclass8.cpp:41
    #14 0x0000000100007644 in CppUnit::TestCaller<newtestclass8>::runTest (this=0x100414b20) at TestCaller.h:166
    #15 0x0000000100066234 in CppUnit::TestCaseMethodFunctor::operator() (this=0x100414b20) at TestCase.cpp:32
    #16 0x000000010005ffb4 in CppUnit::DefaultProtector::protect (this=0x100414530, functor=@0x100500000, context=@0x7fff5fbff580) at DefaultProtector.cpp:15
    #17 0x0000000100064841 in CppUnit::ProtectorChain::ProtectFunctor::operator() (this=0x100414b20) at ProtectorChain.cpp:20
    #18 0x00000001000644d0 in CppUnit::ProtectorChain::protect (this=0x100414290, functor=@0x7fff5fbff600, context=@0x7fff5fbff570) at ProtectorChain.cpp:77
    #19 0x000000010006b0e0 in CppUnit::TestResult::protect (this=0x7fff5fbff920, functor=@0x100500000, test=0x7fff5fbff580, shortDescription=@0x100500000) at TestResult.cpp:178
    #20 0x0000000100065e45 in CppUnit::TestCase::run (this=0x100414b20, result=0x7fff5fbff920) at TestCase.cpp:92
    #21 0x0000000100066375 in CppUnit::TestComposite::doRunChildTests (this=0x100413e80, controller=0x7fff5fbff920) at TestComposite.cpp:64
    #22 0x00000001000662a1 in CppUnit::TestComposite::run (this=0x100413e80, result=0x7fff5fbff920) at TestComposite.cpp:23
    #23 0x0000000100066375 in CppUnit::TestComposite::doRunChildTests (this=0x100414a60, controller=0x7fff5fbff920) at TestComposite.cpp:64
    #24 0x00000001000662a1 in CppUnit::TestComposite::run (this=0x100414a60, result=0x7fff5fbff920) at TestComposite.cpp:23
    #25 0x000000010006b070 in CppUnit::TestResult::runTest (this=0x7fff5fbff920, test=0x100414a00) at TestResult.cpp:145
    #26 0x000000010006d6c6 in CppUnit::TestRunner::run (this=0x100414b20, controller=@0x100414b20, testPath=@0x100414b20) at TestRunner.cpp:96
    #27 0x00000001000230ab in main () at newtestrunner13.cpp:30

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    230
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 230
    Points : 132
    Points
    132
    Par défaut
    et si on retire l'héritage de boost::uncopyable on a moins de "This thread class does not have a run method !" et autant d'exceptions

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

    NVI + virtuelle pure devrait embêter ton compilateur si tu as un pb :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class OPThread : boost::noncopyable
    {
    // [...]
       void run(void) // la fonction n'est plus virtuelle
       {do_run();}
    private:
       virtual void do_run()=0;
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class ThreadTest
    {
    //[...]
    private:
       virtual void do_run()
       {
       }
    };
    Môsieur vient du Java ou de .Net ?
    Pas besoin de this-> en C++ (sauf cas très très particulier)

    running_ et should_stop_, ça pue à 100 mètres.

Discussions similaires

  1. [XL-2010] Selection.find, comportement erratique?
    Par CoriS FrosT dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 22/11/2013, 10h23
  2. [PC fixe] Comportement erratique non lié à l'OS
    Par Arom77 dans le forum Ordinateurs
    Réponses: 4
    Dernier message: 06/01/2012, 16h36
  3. Comportements erratiques avec tp_attr : Effets de bord de Py_FindMethod ?
    Par Elenaher dans le forum Interfaçage autre langage
    Réponses: 0
    Dernier message: 23/06/2010, 14h59
  4. Comportement bizarre du "this" avec de l'héritage
    Par fcx35 dans le forum Débuter
    Réponses: 3
    Dernier message: 05/02/2009, 19h32

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