2
class base
{
    virtual ~base();
};

class der1 :public base
{
    int i;
}

class der2 :public base //I used double that der2 is bigger than der1
{
    double d;
}

int main()
{
   base* ptr = new der2;
   ptr->~base(); //Destructor call just for the
                 //case that the der2 had a pointer member

   der1* ptr2 = static_cast<der1*>(ptr);
   *ptr2 = der1();

   delete ptr;

   return 0;
}

What would happen if you would execute the code shown above? Would this produce a memory leak and if yes why? Is there a possibility to use the taken memory for different types without releasing it first? (Please no answers like why should you need this, it's just interest)

Edit: The ~base() does nothing because this is an example.

Mango
  • 362
  • 1
  • 14

1 Answers1

3

It's undefined behaviour since you assign to, and delete an object after its lifetime has ended, which is forbidden by C++11, [basic.life]/5:

after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that refers to the storage location where the object will be or was located may be used but only in limited ways. The program has undefined behavior if:

  • the object will be or was of a class type with a non-trivial destructor and the pointer is used as the operand of a delete-expression
  • the pointer is used to [...] call a non-static member function of the object

(plus a few other restrictions.) You try to do both of these things.

If you were to fix this, by creating a new object in the old memory rather than assigning to it as if there were already an object there:

der1* ptr2 = new (ptr) der1;

then it's still undefined behaviour, as stated in C++11, [basic.life]/7

If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object [...] can be used to manipulate the new object, if [...] the new object is of the same type as the original object

(plus a few other conditions). You use an pointer to the old object to manipulate (specifically, to delete) the new object of a different type.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Thanks, but by the way undefined behavior yes, but actually no leaks what I think is realy strange. (I tried it with dr Memory) – Mango May 05 '15 at 12:35
  • @Mango: Why would you expect a memory leak? `delete` will call `operator delete` to deallocate the memory previously allocated by `operator new`, which will probably do the right thing despite whatever undefined behaviour you've caused. – Mike Seymour May 05 '15 at 12:48
  • Well, I wasn't sure if the size of allocated memory weren't stored in the pointer type, sorry I'm in my first year of programming, I'm still not far enough to know something like that 100% sure so I asked for. – Mango May 05 '15 at 12:54
  • May I ask what kind of undefined behavior could happen through this? Because actually I could take care of the object sizes and so nothing should happen as long I use the memory for smaller objects (except that it's still undefined behavior) or am I missing something? – Mango May 05 '15 at 16:24
  • @Mango: No-one can answer that since undefined behaviour is, by nature, undefined. You can make it well-defined by allocating memory separately, then creating and destroying objects in that memory using with placement-new and destructor calls. – Mike Seymour May 05 '15 at 16:28
  • Yes of course, that's one of the possibilities but I would like to set that up without passing the memory management so often because relocating memory can take time, is there another possibility to re-use the old memory without undefined behavior (if not, still not so bad) – Mango May 05 '15 at 16:33
  • The standard quote says if these conditions are met, then `ptr` can be used to manipulate the newly created object. As they are not met, `ptr` cannot be used (as it points to the wrong type). The quote says nothing about using `ptr2`? – Yakk - Adam Nevraumont May 25 '15 at 02:41
  • @Yakk: I've no idea what you're asking. The quote refers to "any pointer that refers to the storage location", which in this case means both pointers. – Mike Seymour May 25 '15 at 10:21
  • "a pointer that pointed to the original object" isn't any pointer to the storage location. So that does not apply. After the placement `new` the storage has been reused (only semi-normative definition of reuse is in an example, where `new (this) D2; // reuses storage — ends the lifetime of *this` is explicitlu called reuse) so the rest of the UB quotes are not applicable once the `new` completes? – Yakk - Adam Nevraumont May 25 '15 at 11:36
  • @Yakk: OK, I see what you mean. Yes, the use of `ptr2` after placement-new is well-defined. `delete ptr` is not. I'll correct the answer so it doesn't suggest that the assignment to `*ptr2` is UB. – Mike Seymour May 25 '15 at 11:41
  • http://stackoverflow.com/q/30423539/1774667 is someone misunderstanding you, which is how I wandered by. – Yakk - Adam Nevraumont May 25 '15 at 13:55