首页 > 其他分享 >pure virtual method called错误

pure virtual method called错误

时间:2022-09-26 14:45:38浏览次数:38  
标签:thread derived virtual base pure called

今天在做pthread多线程序设计时遇到这个错误:

pure virtual method called terminate called without an active exception

找了好久,才发现原因,delete一个正在使用的资源(在多线程环境下才可能发生)就会引起。

我在国外的网站上找到的解释:

I spent about two hours today trying to debug a race condition in a multi-threaded C++ app today… definitely not a fun thing to do. The worst part? The runtime diagnostics weren’t giving me anything useful to work with! Sometimes things just worked, sometimes I got segmentation faults inside old, well-tested parts of the application. At one point, I saw this error pop up:

pure virtual method called
terminate called without an active exception
Aborted

What? I know I can’t instantiate a class that has any pure-virtual methods, so how did this error show up? To debug it, I decided to replace all of the potentially-erroneous pure virtuals with stub functions that printed warnings to stderr. Lo and behold, I confirmed that polymorphism wasn’t working in my application. I had a bunch of Deriveds sitting in memory, and yet, the Base methods were being called.

Why was this happening? Because I was deleting objects while they were still in use. I don’t know if this is GCC-specific or not, but something very curious happens inside of destructors. Because the object hierarchy’s destructors get called from most-derived to least-derived, the object’s vtable switches up through parent classes. As a result, at some point in time (nondeterministic from a separate thread), my Derived objects were all really Bases. Calling a virtual member function on them in this mid-destruction state is what caused this situation.

Here’s about the simplest example I can think of that reproduces this situation:


#include
#include
struct base
{
virtual ~base() { sleep(1); }
virtual void func() = 0;
};
struct derived : public base
{
virtual ~derived() { }
virtual void func() { return; }
};
static void *thread_func(void* v)
{
base *b = reinterpret_cast<base*>(v);
while (true) b->func();
return 0;
}
int main()
{
pthread_t t;
base *b = new derived();
pthread_create(&t, 0, thread_func, b);
delete b;
return 0;
}

So what’s the moral of the story? If you ever see the error message pure virtual method called / terminate called without an active exception, check your object lifetimes! You may be trying to call members on a destructing (and thus incomplete) object. Don’t waste as much time as I did.





////////////////////////////

3 comments


In my case I have a base class that provides a thread for asynchronous processing. This is started in the base class constructor.

A derived class defines a thread function as well as pure virtual functions. The thread function can sometimes start calling the pure virtual functions before the later constructors are called in the ‘main’ thread.

My fix is inelegant - put a delay into the thread startup code.
There must be a better way?


 


 

 

I ran into another scenario: automatic variable. When it was passed as an argument to pthread_create(), it was still there, but because execution of pthread_create() may be delayed, the automatic variable–a derived object–ran off the end of the (member) function.

I fixed it by using a member variable, which obviously lives longer than that function.


 

I meant execution of the thread made by pthread_create() may be delayed, not itself.

 

标签:thread,derived,virtual,base,pure,called
From: https://www.cnblogs.com/eastgeneral/p/16730911.html

相关文章