首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当实现一个boost::thread包装器接口时,“纯虚方法调用”

当实现一个boost::thread包装器接口时,“纯虚方法调用”
EN

Stack Overflow用户
提问于 2010-07-02 01:59:16
回答 2查看 3.1K关注 0票数 6

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

代码语言:javascript
复制
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)));
    }
};

当我实现它的时候,用下面的话说:

代码语言:javascript
复制
class A : public Thread {
    void work() {}
};

在:

代码语言:javascript
复制
A a; a.run();

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

事先谢谢你。

致以敬意,

神秘先生

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-07-02 03:02:03

只有当你的程序立即退出时,你的崩溃才会发生:它调用A类的析构函数,在新启动的线程有机会被调度之前完成并调用thread的析构函数。然后线程调用您的虚拟函数,但是类A不再存在,因此它尝试调用线程的do_work(),后者调用纯虚拟功()。下面是带有额外输出的程序:

代码语言:javascript
复制
run() started 
run() ended
~A() started
~A() ended
~Thread() started
catch_up() started
do_work() started
pure virtual method called

就标准而言,我认为这是未定义的行为,因为当从线程调用do_work()时,对象的引用(boost::ref(*this))已经结束(析构函数调用开始)。

解决方案:让线程在销毁对象之前执行:

代码语言:javascript
复制
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."

票数 6
EN

Stack Overflow用户

发布于 2010-07-02 02:07:12

我在这里有点冒险,但我怀疑问题出在你的线程析构函数上:

代码语言:javascript
复制
virtual ~Thread() { 
    catch_up(); 
    delete m_thread; 
} 

如果线程还没有启动,在析构函数中调用catch_up()将使用线程的vtable而不是A的vtable启动boost线程,就像在C++中析构函数的点vtable匹配析构函数类型的作用域,而不是最派生的vtable。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3160403

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档