Object-Oriented Suicide or delete this;
Asked Answered
C

3

7

The following code compiled with MSVC9.0 runs and outputs Destructor four times, which is logical.

#include <iostream>
class SomeClass
{
public:
   void CommitSuicide()
   {
      delete this;
   }
   void Reincarnate()
   {
      this->~SomeClass();
      new (this) SomeClass;
   }
   ~SomeClass()
   {
      std::cout  << "Destructor\n";
   }
};

int main()
{
   SomeClass* p = new SomeClass;
   p->CommitSuicide();
   p =  new SomeClass;
   p->Reincarnate();
   p->~SomeClass(); //line 5
   p->CommitSuicide();
}

I think the first 4 lines of code in main do not result in undefined behavior (although not entirely sure about the delete this; thing). I would like to have a confirmation or < placeholder for confirmation's antonym > of that. But I have serious doubts about lines 5 and 6. It is allowed to explicitly call the destructor, isn't it? But is the lifetime of the object considered to have finished after that? That is, is invocation of another member after the explicit call of the destructor allowed (defined)?

To summarize, which parts of the above code (if any) result in undefined behavior (technically speaking)?

Calamine answered 18/10, 2010 at 13:29 Comment(2)
But the constructor is only called 3 times, so how is calling the destructor 4 times logical? It would bomb as soon as the class gets (non-trivial) data members.Neron
< placeholder for confirmation's antonym > - it's called "denial"Possie
N
2

p->~SomeClass(); //line 5

p->CommitSuicide(); //line 6

Line (6) definitely invokes Undefined Behaviour.

That is, is invocation of another member after the explicit call of the destructor allowed (defined)?

No! Your assumption is correct.

Nefen answered 18/10, 2010 at 13:43 Comment(4)
line 6 "should" give a memory access error (segfault on linux) because the address space previously occupied by the instance of SomeClass pointed to by p, "should" have been freed properly by the OS. Or does the destructor do a late call to delete?Possie
@slashmais: No, there's no such guarantee, and very few implementations work like that. Most implementations have a notion of "free space", which is memory allocated by the OS to the program, yet not containing any objects. Memory reclaimed from deleted objects is recycled into this "free space", to be used by future objects.Ailee
Yes, I thought it would be something like that. Explains line 6 succeeding then because the space hasn't been recycled yet.Possie
@Possie Line 5 does not deallocate the memory used by the object. It only destructs the object. The memory that was being used, remains allocated. Therefore new (this) SomeClass; is valid code (which constructs the object, without allocating memory). Line 5 is not wrong, but the object must be reconstructed before the memory used can be freed using delete. AFAIK, there is no means to deallocate memory allocated by new, without calling the destructor.Generalissimo
P
6

The delete this; is fine. The last p->CommitSuicide(); gives undefined behavior because you already destroyed the object in "line 5".

Parishioner answered 18/10, 2010 at 13:43 Comment(0)
N
2

p->~SomeClass(); //line 5

p->CommitSuicide(); //line 6

Line (6) definitely invokes Undefined Behaviour.

That is, is invocation of another member after the explicit call of the destructor allowed (defined)?

No! Your assumption is correct.

Nefen answered 18/10, 2010 at 13:43 Comment(4)
line 6 "should" give a memory access error (segfault on linux) because the address space previously occupied by the instance of SomeClass pointed to by p, "should" have been freed properly by the OS. Or does the destructor do a late call to delete?Possie
@slashmais: No, there's no such guarantee, and very few implementations work like that. Most implementations have a notion of "free space", which is memory allocated by the OS to the program, yet not containing any objects. Memory reclaimed from deleted objects is recycled into this "free space", to be used by future objects.Ailee
Yes, I thought it would be something like that. Explains line 6 succeeding then because the space hasn't been recycled yet.Possie
@Possie Line 5 does not deallocate the memory used by the object. It only destructs the object. The memory that was being used, remains allocated. Therefore new (this) SomeClass; is valid code (which constructs the object, without allocating memory). Line 5 is not wrong, but the object must be reconstructed before the memory used can be freed using delete. AFAIK, there is no means to deallocate memory allocated by new, without calling the destructor.Generalissimo
M
0

"delete this" is ok as long as you do not attempt to call any code of that object after the deletion (not even the destructor). So a self deleting object shoud only be placed at the heap and shoud have a private destructor to protect from creation on the stack.

I dont know if a direct call to the destructor leads to undefined behaviour but a userdefined delete-operator would'nt get executed.

Mcmasters answered 18/10, 2010 at 13:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.