0

I am going through the tutorial from this link. It clearly says in it's second point is that after deleting the object via this, then any member of the deleted object should not be accessed after deletion. But still after deleting the object output is "x = 0 y = 0". Here is my code:

 #include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test(int x = 0, int y = 0) { this->x = x; this->y = y; }
void setX(int a) { x = a; }
void setY(int b) { y = b; }
void destroy() { delete this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test *obj;
obj = new Test;
obj->destroy();
obj->print();
return 0;
}
Uchiha_itachi
  • 103
  • 1
  • 2
  • 13

2 Answers2

3

This is undefined behavior. The memory previously allocated to x and y just hasn't been overwritten yet when you call print(). A good practice is to set obj = nullptr; immediately after you delete it.

Carlton
  • 4,217
  • 2
  • 24
  • 40
  • but the thing is, I am still calling the print() via the same object I deleted earlier right. Then how print() is being executed. – Uchiha_itachi Aug 05 '15 at 17:53
  • @Uchiha_itachi undefined means undefined. It might work once and crash the next 5 times, or it may work 5 times. Either way, what you are doing you should not be doing. – crashmstr Aug 05 '15 at 17:54
  • `obj` still has a non-null value to it, even after you delete the object that it pointed to. The data from that object is still in memory (in this case), and `obj` still points to it. So, voila, you can still access the members of that object. This will likely work until that memory is finally overwritten by some other data, but you definitely shouldn't rely on this behavior. This is one of my most-hated bugs, since the code might work for a long while, then suddenly stop working because you changed some other, unrelated part of your code. This is what `std::unique_ptr` is for. – Carlton Aug 05 '15 at 17:55
0

As Carlton says, the memory was not overwritten, you can try the following code:

int main()
{
    Test *obj;
    obj = new Test;
    obj->destroy();
    Test *another_obj = new Test(7, 8);
    obj->print();
    return 0;
}

This printed x = 7 y = 8 on my machine, you can play around with the code. It probably will give you different results when you try allocating memory between obj->destroy() and obj->print()

The main point is this is undefined behavior

EDIT:

I debugged the code to illustrate it more clear. you can see at first obj's address is 0x100104aa0, then when delete this was executed, the memory was not changed, but, not changing doesn't mean anything, to your program, this means memory 0x100104aa0 is free to use(there's a point here, if the program is going to write to(allocate) some memory, then it makes no difference if the memory is initialized/cleared or not, so for efficiency, free to use memory are not cleared)

Then when I initialized sss, it was allocated at the same address, with new x and y values, note that after the initialization of sss, obj is still pointing to 0x100104aa0, which happens to be the same address as sss, which is the reason calling obj() gives you x = 7 y = 8.

* thread #1: tid = 0x1386d, 0x0000000100000e08 a.out`main + 72 at t.cpp:19, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100000e08 a.out`main + 72 at t.cpp:19
   16   {
   17       Test *obj;
   18       obj = new Test(1, 2);
-> 19       obj->destroy();
   20       Test *sss = new Test(7, 8);
   21       obj->print();
   22       return 0;
(lldb) p obj
(Test *) $5 = 0x0000000100104aa0
(lldb) x $5
0x100104aa0: 01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00  ................
0x100104ab0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
(lldb) n
Process 5010 stopped
* thread #1: tid = 0x1386d, 0x0000000100000e17 a.out`main + 87 at t.cpp:20, queue = 'com.apple.main-thread', stop reason = step over
    frame #0: 0x0000000100000e17 a.out`main + 87 at t.cpp:20
   17       Test *obj;
   18       obj = new Test(1, 2);
   19       obj->destroy();
-> 20       Test *sss = new Test(7, 8);
   21       obj->print();
   22       return 0;
   23   }
(lldb) p obj
(Test *) $6 = 0x0000000100104aa0
(lldb) x $6
0x100104aa0: 01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00  ................
0x100104ab0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
(lldb) n
Process 5010 stopped
* thread #1: tid = 0x1386d, 0x0000000100000e4b a.out`main + 139 at t.cpp:21, queue = 'com.apple.main-thread', stop reason = step over
    frame #0: 0x0000000100000e4b a.out`main + 139 at t.cpp:21
   18       obj = new Test(1, 2);
   19       obj->destroy();
   20       Test *sss = new Test(7, 8);
-> 21       obj->print();
   22       return 0;
   23   }
(lldb) x $6
0x100104aa0: 07 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00  ................
0x100104ab0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
(lldb) p sss
(Test *) $7 = 0x0000000100104aa0
(lldb) p obj
(Test *) $8 = 0x0000000100104aa0
(lldb)
shengy
  • 9,461
  • 4
  • 37
  • 61