user707549
user707549

Reputation:

Is this safe to deallocate memory from a pointer of a different type than when it was allocated?

I have a question about deallocating memory in C++:

typedef struct type1
{
   int a;
   int b;
   float c;
} Type1;

typedef struct type2
{
   int a;
   int b;
} Type2;

void *p = new Type1;

delete (Type2 *)p;

In this case, will be the memory area pointed by p be deleted completely even after p was cast to type of different size?

Upvotes: 7

Views: 249

Answers (3)

LihO
LihO

Reputation: 42103

Although this question was perfectly answered by James already, I would like to point out one thing:

In proper C++ code, you'll almost never end up working with void pointers, which means your code would probably look like this:

SubType *p = new SubType;
BaseType* pB = (BaseType*)p;
delete pB;

in this case, even if the BaseType would have proper virtual constructor, there is still possible undefined behavior if the SubType is not derived from the BaseType. Common C-style cast isn't very lucky choice here.

But in case you would use dynamic_cast, compiler would most likely not let you do that in case that p doesn't point to object of polymorphic type. And even in case that p points to object of polymorphic type, but BaseType wouldn't be base type of SubType, dynamic_cast would return NULL and you could handle this state appropriately:

SubType *p = new SubType;
BaseType* safePtr = dynamic_cast<BaseType *>(p);
if (!safePtr) // p doesn't point to object of type derived from BaseType
    ...       // handle this situation
else          // p points to object of polymorphic type derived from BaseType
    delete safePtr;

Upvotes: 0

James McNellis
James McNellis

Reputation: 355207

The behavior is undefined. In this case, the dynamically allocated object may only be deleted via a pointer of type Type1.

First, by using the pointer obtained by (Type2 *)p in the delete expression, you violate the aliasing rules. There is a limited set of types via which the object pointed-to by p may be used. The rules from C++03 may be found in an answer to another question. The C++11 rules are similar (the differences are not relevant to the answer to your question).

Even if the program did not violate the strict aliasing rules, it would violate the requirements of the delete expression. The specification states (C++11 §5.3.5[expr.delete]/3):

if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined.

In your delete expression, the static type of the object is Type2, whereas the dynamic type is Type1. The types are different, but the static type is not a base class of the dynamic type.

Upvotes: 14

bmargulies
bmargulies

Reputation: 100153

That would be a really bad idea, as you would be asking the compiler to arrange to run Type2::~Type2 on a Type1 pointer, and that destructor might reference off the end of the object.

In conventional environments, the eventual free of the memory would be alright, because operator delete calls free which does not care what type you called it at compile time. However, in a not so conventional environment, it could be a disaster.

Upvotes: 4

Related Questions