实现boost :: thread包装器接口时“调用纯虚方法”

时间:2010-07-01 17:59:16

标签: c++ boost multithreading pure-virtual

我有一个小包装器,它集中了与线程相关的内容:

class Thread {
protected:
    boost::thread *m_thread;

    virtual void work() = 0;

    void do_work() {
        work();
    }

public:
    Thread() : m_thread(NULL) {}
    virtual ~Thread() {
        catch_up();
        delete m_thread;
    }

    inline void catch_up() {
        if(m_thread != NULL) {
            m_thread->join();
        }
    }

    void run() {
        m_thread = new boost::thread(boost::bind(&Thread::do_work, boost::ref(*this)));
    }
};

当我实施它时,请说明如下:

class A : public Thread {
    void work() {}
};

在:

A a; a.run();

我得到了一个运行时终止,显示了一个非常“纯粹的虚拟方法”。我认为这是boost :: bind参数,但我不知道如何说“使用虚拟纯实现”......

先谢谢。

问候,

Mystère先生

2 个答案:

答案 0 :(得分:6)

只有当你的程序立即退出时才会发生崩溃:它会调用类A的析构函数完成并在新启动的线程有机会被调度之前调用Thread的析构函数。然后线程调用你的虚函数,但是类A不再存在,所以它试图调用Thread的do_work(),它调用纯虚函数()。这是你的额外输出程序:

run() started 
run() ended
~A() started
~A() ended
~Thread() started
catch_up() started
do_work() started
pure virtual method called

标准方面,我认为这是未定义的行为,因为对象的生命周期已经结束(析构函数调用开始),当使用对它的引用(boost::ref(*this))从线程调用do_work()时。 p>

解决方案:在破坏对象之前让线程执行:

A a; a.run();
a.catch_up();

或者,正如boost.thread文档所说,"the user of Boost.Thread must ensure that the referred-to object outlives the newly-created thread of execution."

答案 1 :(得分:1)

我在这里出去了,但我怀疑你的Thread析构函数存在问题:

virtual ~Thread() { 
    catch_up(); 
    delete m_thread; 
} 

如果线程还没有启动,在析构函数中调用catch_up()将使用Thread的vtable而不是A来启动boost线程,就像在析构函数中的C ++中vtable匹配类型的范围一样析构函数,而不是最衍生的vtable。