在纯虚拟类的析构函数中等待线程死亡会导致运行时错误

Waiting for thread to die in destructor of pure virtual class causes runtime error

本文关键字:运行时错误 线程 等待 虚拟 析构函数      更新时间:2023-10-16

我正试图在纯虚拟类的析构函数中等待线程死亡。这段代码编译得很好,看起来很有意义。但是,运行时会出现以下错误:

pure virtual method called
terminate called without an active exception
Aborted (core dumped)

这是我的程序:

#include <boost/thread.hpp>
#include <iostream>
class Test {
    protected:
        int x;
        boost::thread th;
    public:
        Test(void): x(10) {};
        ~Test(void);
        virtual void operator()(void);
        void run(void);
        virtual void a(void) = 0;
        void wait(void);
};
Test::~Test(void) {
    this->wait();
}
void Test::operator()(void) {
    this->a();
    x += 10;
    std::cout << "Current Value: " << x << std::endl;
}
void Test::run(void) {
    this->th = boost::thread(&Test::operator(), this);
}
void Test::wait(void) {
    this->th.join();
}
class Test1 : public Test {
    public:
        virtual void a(void);
};
void Test1::a(void) {
    x--;
}
main() {
    Test1 test;
    test.run();
    //test.wait();
}

预期结果是19。我可以通过在对象离开作用域而不是进入析构函数之前将对Test::wait()的调用放在main()中来获得它。当从Test中删除纯虚拟方法a()时,不会发生异常。

我的问题是:

  1. 由于Test::a()不在析构函数的调用链中,错误指的是什么虚拟方法
  2. 如果存在这样的歧义,为什么要编译代码

我猜其中一个的答案就是另一个。。。

附言:如果重要的话,我正在Arch Linux上运行g++(GCC)4.9.1 20140903(预发布),内核版本3.17.2-1GNUbash中,版本4.3.30(1)-发布

当您从构造函数/析构函数调用虚拟函数时,问题与问题有关。在这种情况下,从基类析构函数Test::~Test()调用wait(),这意味着派生类Test1已经被析构函数,并且虚拟表更新为基类Test。看起来独立线程中的虚拟调用发生在那个之后,您得到了纯虚拟方法调用。所以行为就像您从Test的析构函数间接调用a()

当显式调用wait()时,它会在test1实例被销毁之前等待,并且工作正常。

与此问题无关,Test类的dtor应该是虚拟的,因为您有虚拟方法。