Reputation: 13
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...
Upvotes: 1
Views: 2241
Reputation: 13
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
Upvotes: 0
Reputation: 4659
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.
Upvotes: 2
Reputation: 137810
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.
Upvotes: 2
Reputation: 106549
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)
Upvotes: 4
Reputation: 308206
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.
Upvotes: 2
Reputation: 57248
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.
Upvotes: 2