views:

143

answers:

6

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

Need some help... Thanks in advance

+1  A: 

If KillObject always deletes a Base *, why does it take a void *? Change ptr to be Base * and get rid of the cast. Then if the thing passed in is a Base *, a Derived *, or a MoreDerived *, it will work.

Graeme Perrow
+2  A: 

By casting the pointer to void * you're removing the compiler's knowledge of how to convert up and down the inheritance tree. 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.

Mark Ransom
a pointer is a pointer. The compilers knowledge is in the vtable of the thing it points to; when he casts it back all should be good
pm100
+1 Mark's warning to a beginner looks deeply true however.
Stephane Rolland
@pm100, it's more complicated than that. http://en.wikipedia.org/wiki/Virtual_method_table#Multiple_inheritance_and_thunks
Mark Ransom
Hi guys, thank you so much for all responses.
MaaTt
+3  A: 

In C++, a cast often results in a change of the address of the pointer. You need to cast to a Base * before casting to void *, or you have undefined behavior. (Casting to/from Void * is okay, but when casted back it needs to be the exact same type on either end)

Billy ONeal
I suppose by doing <code>Base* ptrToBase = obj;</code>, I have already done a static_cast to <code>Base*</code>??
MaaTt
I have updated to post as an answer. I suppose by doing <code>Base* ptrToBase = obj;</code>, I have already done a static_cast to <code>Base*</code>??
MaaTt
A: 

I think you're thinking of dynamic_cast<void*> which obtains a pointer to a most-derived object.

You don't need to go through a void* just to delete an object of polymorphic type. Just take whatever pointer you have and delete it, be it a Base* to a MoreDerived object or a MoreDerived*. There is no need for a Kill method.

Potatoswatter
+1  A: 

If you static_cast to void* then standard only guarantees that static_cast to the original pointer type will work correctly. As mentioned previously you either need dynamic_cast or need to static_cast to Base* first and then to void*. static_cast from void* to Base* should then work correctly.

Tomek
A: 

Hi Guys, 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

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;, I have already done a static_cast to Base*??

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 Potatoswatter: I think in "More Effective C++" they mentioned using dynamic_cast< void* > but I have failed to find that sentence again. I will give this a go and let you know the result.

Thanks again

MaaTt
Why would you want to delete object in separate thread???
Tomek