I have a piece of code where I can call the destructor multiple times and access member functions even the destructor was called with member variables' values preserved. I was still able to access member functions after I called delete
but the member variables were nullified (all to 0). And I can't double delete
. Please kindly explain this.
#include <iostream>
using namespace std;
template <typename T>
void destroy(T* ptr)
{
ptr->~T();
}
class Testing
{
public:
Testing() : test(20)
{
}
~Testing()
{
printf("Testing is being killed!\n");
}
int getTest() const
{
return test;
}
private:
int test;
};
int main()
{
Testing *t = new Testing();
cout << "t->getTest() = " << t->getTest() << endl;
destroy(t);
cout << "t->getTest() = " << t->getTest() << endl;
t->~Testing();
cout << "t->getTest() = " << t->getTest() << endl;
delete t;
cout << "t->getTest() = " << t->getTest() << endl;
destroy(t);
cout << "t->getTest() = " << t->getTest() << endl;
t->~Testing();
cout << "t->getTest() = " << t->getTest() << endl;
//delete t; // <======== Don't do it! Double free/delete!
cout << "t->getTest() = " << t->getTest() << endl;
return 0;
}
C++ draft standard §12.4.12
As noted by others, this doesn't mean the implementation will always do something obviously unwanted (like a segmentation fault). It means it can do whatever is most convenient.
Just because you are accessing a not longer valid object doesn't mean your program has to explode, it just means your program can explode.
It is undefined behavior, which means anything can happen, it might even appear to do the correct thing.
This is an exhibit of undefined behavior. Call a member function through a pointer that's been deleted and anything goes - the compiler and runtime aren't required to check for this error, but you certainly can't count on this working.
This falls into a similar category as using memory that's been freed - you might find your old data there (or you might not). You might cause the program to crash (or not). You might even be able to change the data without anything complaining.
But in any case, it's a programming error.
You've invoked undefined behaviour, all bets are off.
Expressly calling the destructor, as you do in
destroy()
, and directly inmain()
doesn't actually cause an object to be destroyed in C++. Only thedelete
statement in this code does that. Since T's destructor is benign (it just prints), this has almost no effect.Since none of the member functions are virtual, calling them after the destruction will still get to the right code to execute. Once there, the
this
pointer may be invalid (after your call todelete
), but that doesn't stop the code from dereferencing the pointer and returning the value of theint
member value.You really shouldn't call a class' destructor (unless you used placement new) however to answer your question, once memory has been deleted accessing pointers to that memory results in undefined behavior. In your case it appears as though the memory you are using has been freed for future use but it hasn't yet been overwritten. So you are still able to access it but there are no guarantees as to when that memory is going to be used by something else.