简体   繁体   English

C ++虚拟析构函数崩溃

[英]C++ Virtual Destructor Crash

I have the following class hierarchy: 我具有以下类层次结构:

class Base  
{  
public:  
    virtual ~Base();  
};  
class Derived : public Base  
{  
public:  
    virtual ~Derived();  
};  
class MoreDerived : public Derived  
{  
public:  
    virtual ~MoreDerived();  
};  

along with an objects 连同物体

Base* base = new Base();
MoreDerived* obj = new MoreDerived(*base);  

There is a part of code where I need to delete the MoreDerived object using a thread, thus having to cast it to void* first. 在代码的一部分中,我需要使用线程删除MoreDerived对象,因此必须首先将其强制转换为void *。 In the thread, I have 在线程中,我有

void KillObject(void* ptr)  
{  
    delete static_cast<Base*>(ptr);  
}  

Non of the pointers are NULL, and void* ptr IS a MoreDerived* (or at least a Base*), but the application still crashes... 非指针是NULL,并且void* ptr MoreDerived *(或至少是Base *),但是应用程序仍然崩溃...

In C++, a cast often results in a change of the address of the pointer. 在C ++中,强制转换通常会导致指针地址的更改。 You need to cast to a Base * before casting to void * , or you have undefined behavior. 您需要在强制转换为void *之前强制转换为Base * void * ,否则您的行为不确定。 (Casting to/from Void * is okay, but when casted back it needs to be the exact same type on either end) (向/从Void *投射是可以的,但是当被投射回它时,两端必须是完全相同的类型)

If KillObject always deletes a Base * , why does it take a void * ? 如果KillObject总是删除一个Base * ,为什么它需要一个void * Change ptr to be Base * and get rid of the cast. ptr更改为Base *并摆脱强制转换。 Then if the thing passed in is a Base * , a Derived * , or a MoreDerived * , it will work. 然后,如果传入的东西是Base *Derived *MoreDerived * ,它将起作用。

By casting the pointer to void * you're removing the compiler's knowledge of how to convert up and down the inheritance tree. 通过将指针强制转换为void *您将删除编译器有关如何上下转换继承树的知识。 This is especially a problem when there is multiple inheritance, as two pointers to the same object won't necessarily have the same value! 当存在多个继承时,这尤其成问题,因为指向同一对象的两个指针不一定具有相同的值!

Don't do that. 不要那样做

If you static_cast to void* then standard only guarantees that static_cast to the original pointer type will work correctly. 如果将static_cast设置为void *,则standard仅保证将static_cast转换为原始指针类型将正常工作。 As mentioned previously you either need dynamic_cast or need to static_cast to Base* first and then to void*. 如前所述,您要么需要dynamic_cast,要么需要先static_cast到Base *,然后再void *。 static_cast from void* to Base* should then work correctly. 从void *到Base *的static_cast应该可以正常工作。

I think you're thinking of dynamic_cast<void*> which obtains a pointer to a most-derived object. 我认为您正在考虑dynamic_cast<void*> ,它获取指向最衍生对象的指针。

You don't need to go through a void* just to delete an object of polymorphic type. 您无需经过void*即可删除多态类型的对象。 Just take whatever pointer you have and delete it, be it a Base* to a MoreDerived object or a MoreDerived* . 只需获取您拥有的任何指针并将其delete ,它可以是MoreDerived对象的Base*MoreDerived* There is no need for a Kill method. 不需要Kill方法。

Thanks you so much for all the responses. 非常感谢您的所有回复。

Just to clarify the situation and elaborate on the code some more, I am using gcc 4.1.2 on CentOS, and he missing type in static_cast is a StackOverflow formatting error, and I have 只是为了澄清情况并详细说明代码,我在CentOS上使用gcc 4.1.2,他在static_cast中缺少类型是StackOverflow格式错误,并且我有

void KillObject(void* ptr)
{
delete static_cast< Base* >(ptr);
};
// There is a reason for the following as this is a snipet and stuff gets passed around
Base* base = new Base();
MoreDerived* obj = new MoreDerived( * base );
Base* ptrToBase = obj;
// Use ptrToBase in code with no problems
// Delete object, illustrative only - have to cast to void* to pass to API
pthread_run( ... , KillObject , (void*)ptrToBase);

Re Billy O'Neal: I suppose by doing Base* ptrToBase = obj; 关于Billy O'Neal:我想通过做Base* ptrToBase = obj; , I have already done a static_cast to Base* ?? ,我已经完成了对Base*的static_cast?

Re Mark Ransom: By printing out the pointer and steps the delete does through, I see that the pointer has the same address all the way through and it crashes at ~MoreDerived() . Re Mark Ransom:通过打印出指针并逐步执行删除操作,我发现指针一直具有相同的地址,并且在~MoreDerived()处崩溃。

Re Potatoswatter: I think in "More Effective C++" they mentioned using dynamic_cast< void* > but I have failed to find that sentence again. 关于Potatoswatter:我认为他们在“更有效的C ++”中提到使用dynamic_cast< void* >但是我没有再次找到该句子。 I will give this a go and let you know the result. 我会尝试一下,让您知道结果。

Thanks again 再次感谢

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM