我的情况是退出软件时偶尔产生这种错误,也算是多线程中的一个使用不当的情况。
简化后的模型如下:
class A
{
public:
virtual void vf() = 0;
void fa() {
vf();
}
~A() {
fa();
}
private:
Thread *thread;
};
class AA : public A
{
virtual void vf() { /*do something*/ }
};
int main()
{
AA *aa = new AA;
delete aa;
return 0;
}

没错就是在基类的构造/析构函数中对虚函数进行了调用。实际的情况是:线程T1和T2持有同一个AA对象的指针,当T1在对AA进行析构,执行到A::~A()中时,T2还在跑着AA::vf(),因为一旦进入A::~A()后,对象的虚表指针已经被重新指向了基类A的虚表,不再是AA的了,然后在这个间隙里T2产生了对vf()的调用,就抛出异常了。
遇到这个情况,简单的做法是先在AA析构之前先让线程T2终止。然而软件将线程安置在基类中(如上面A::thread),要求派生类去执行停止线程动作,这样便会使得接口的易用性下降,因为很有能会忘记执行了,就跟忘记释放内存一样,在不知不觉中又引回了这个问题。
最后还是去掉了vf的纯虚属性,变成一个实现为空的普通虚函数了。
