【问题标题】:"pure virtual method called" when implementing a boost::thread wrapper interface实现 boost::thread 包装器接口时“调用纯虚拟方法”
【发布时间】:2011-03-10 18:41:03
【问题描述】:

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

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 参数,但我不知道怎么说“使用虚拟纯实现”...

先谢谢了。

问候,

神秘先生

【问题讨论】:

    标签: c++ boost multithreading pure-virtual


    【解决方案1】:

    我在这里很困难,但我怀疑问题出在你的线程析构函数上:

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

    如果线程尚未启动,则在析构函数中调用catch_up() 将使用 Thread 的 vtable 而不是 A 的启动 boost 线程,因为在 C++ 中,在析构函数的位置 vtable 与类型的范围匹配析构函数,而不是派生最多的 vtable。

    【讨论】:

    • 我认为 new 在创建线程句柄后分配它对吗?因此,如果 m_thread 等于 NULL,则检查 catch_up() 足以保护它,以防析构函数比线程的创建速度快。
    • 我指的是 Thread 的析构函数,而不是 boost::thread 的析构函数。
    • 我知道,我也在谈论这个。但是现在我明白了,我想你也指出了,对不起,我的错了;)
    【解决方案2】:

    您的崩溃仅在您的程序立即退出时发生:它调用类 A 的析构函数,该析构函数结束并在新启动的线程有机会被调度之前调用线程的析构函数。。然后线程调用你的虚函数,但是类A不再存在,所以它尝试调用线程的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() 时,对象的生命周期已经结束(析构函数调用开始)。

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

    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."

    【讨论】:

    • 嗯,这很简单...谢谢,你说的很清楚。但是现在我遇到了一个更大的问题(显然是随机布尔值......),我认为调试起来会更加困难。我只是不应该在这里使用我的“小丑”,否则我会显得很需要^^'
    猜你喜欢
    • 2011-01-17
    • 2011-10-03
    • 2019-02-11
    • 2019-07-01
    • 2012-05-04
    • 1970-01-01
    • 2012-06-15
    • 1970-01-01
    • 2011-05-27
    相关资源
    最近更新 更多