Can the member variable be accessed after the destructor is called explicitly?

Radha.sundar's Avatar, Join Date: Jul 2009
Newbie Member
Destructor is used to destroy(release) the Memory which is allocated to object. And it can be called explicitly. In the follwoing code the destructor for objA is called. After that the member of objA is accessed. How can it be possible if the destructor released the memory of objA?


Code: C
#include<iostream.h>
class A
{
    public:
 int a;
 A()
 {
     a=10;
     cout<<"in constructor\n";
 }
 ~A()
 {
     cout<<"in destructor\n";
 }
};
main()
{
    A objA;
    cout<<"a ="<<objA.a<<"\n";
    objA.~A();
    cout<<"a ="<<objA.a<<"\n";
    return 1;
  }

Output :
in constructor
a =10
in destructor
a =10
in destructor

Last edited by SaswatPadhi; 9Jul2009 at 17:34.. Reason: Changed from PHP to C Code Tag
shabbir's Avatar, Join Date: Jul 2004
Go4Expert Founder
Moved to C-C++ Forum
xpi0t0s's Avatar, Join Date: Aug 2004
Mentor
Quote:
Originally Posted by Radha.sundar View Post
Output :
in constructor
a =10
in destructor
a =10
in destructor <--------
The marked line is a clue. The destructor is called automatically when you delete the object, but calling the destructor itself does not free the object.

Also depending on the implementation, destroying an object might not actually change the contents of RAM. So you could access memory after it has been freed, but not reliably because this memory is then available for other code to allocate.
SaswatPadhi's Avatar, Join Date: May 2009
~ Б0ЯИ Τ0 С0δЭ ~
Quote:
Originally Posted by xpi0t0s View Post
The destructor is called automatically when you delete the object, but calling the destructor itself does not free the object.

You mean, when we call a destructor explicitly, the object is not freed !?!?!

Is that true ? I think we can explicitly delete the objects by calling destructors.

Quote:
Originally Posted by xpi0t0s View Post
Also depending on the implementation, destroying an object might not actually change the contents of RAM.
But the memory is marked "unallocated", though not changed.

Quote:
Originally Posted by xpi0t0s View Post
So you could access memory after it has been freed, but not reliably because this memory is then available for other code to allocate.
xpi0t0s's Avatar, Join Date: Aug 2004
Mentor
Quote:
Originally Posted by SaswatPadhi View Post
I think we can explicitly delete the objects by calling destructors.
No, because of the marked line, which shows that EVEN THOUGH the destructor has been called, the compiler thinks it still has to call it.

Calling the destructor is one of those things you should only do if you REALLY KNOW what you are doing (and therefore don't need to ask). If you need to call the destructor, better to make the destructor call some function f() and call f() instead of the destructor.

Anyway, if you want to delete the object, why would you want to call the destructor instead of using the perfectly good "delete object;"?

Proof of concept code. If calling the destructor deletes an object then this should be an infinite loop:
Code:
class foo
{
	char x[10];
public:
	~foo() { };
};

int main(int argc, char* argv[])
{
	for (;;)
	{
		foo *bar=new foo;
		bar->~foo();
	}
	return 0;
}
On my computer this crashes after the process size increases dramatically and fills all available memory (it was char x[1000] but it crashed before I could get to Task Manager and watch the memory grow).

Changed bar->~foo(); to delete bar; and the process remained tiny and took up 100% CPU instead of 100% RAM.


*** Therefore calling a destructor DOES NOT free the object. ***


POC2: accessing object memory after deleting the object:
Code:
class foo
{
public:
	char dummy1[100];
	char x[10];
	char dummy2[100];

	foo(char *str="Hello") { strcpy(x,str); }
	~foo() { };
};

void test1()
{
	for (;;)
	{
		foo *bar=new foo;
		delete bar;
		// bar->~foo();
	}
}

void test2()
{
	foo *bar=new foo;
	delete bar;
	printf("bar->x='%s'\n",bar->x);
}

int main(int argc, char* argv[])
{
	test2();
	return 0;
}
dummy1 and dummy2 were necessary to make this work (using Visual Studio 2008).
The code prints "bar->x='Hello'".
But this is undefined behaviour, because bar has been freed.
Without the dummies, building in Release mode I got
bar->x=''
and in Debug mode I got
bar->x='¦¦¦¦¦¦¦¦¦¦¦¦¦¦'
Interestingly, with dummies and building in Debug mode I got
bar->x='¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦'

But anyway, this is UB because of the delete. So this code is just to prove that you will get unpredictable results if you do stupid things.

Moving the delete after the printf I got the same result in all four configurations (with and without the dummies, and in both Debug and Release mode):
bar->x='Hello'
mayjune's Avatar, Join Date: Jun 2009
Invasive contributor
Code:
    
#include<iostream.h> class A { public: int a; A() { a=10; cout<<"in constructor\n"; } ~A() { cout<<"in destructor\n"; } }; main() { A objA; cout<<"a ="<<objA.a<<"\n"; objA.~A(); /*Error In TC = Member Identifier Expected...?*/ cout<<"a ="<<objA.a<<"\n"; return 1; }
xpi0t0s's Avatar, Join Date: Aug 2004
Mentor
> Error In TC = Member Identifier Expected...?

No idea. Code looks fine to me and even on Warnings Level 4 Visual Studio 2008 doesn't raise an eyebrow. Maybe you're using an old compiler that doesn't support that syntax? For some reason lots of people round here like using Borland C++ v3 from about 1836 even though the Microsoft compilers can be downloaded for free.
Radha.sundar's Avatar, Join Date: Jul 2009
Newbie Member
Thanks all for ur reply. I just try this code to check whether calling destructor explicitly is doing the same job as the one provided by the compiler. So,to destroy an object the operator "delete" should be used (if a pointer to an object is created) and freeing up the memory allocated to the members can be done in the destructor. When the object goes out of scope it will not be no longer valid that time destructor will be called to do the operation mentioned, if any. Am I right?
xpi0t0s's Avatar, Join Date: Aug 2004
Mentor
The destructor is called when you delete the object or let it go out of scope, yes.
xpi0t0s's Avatar, Join Date: Aug 2004
Mentor
Note that if you explicitly call the destructor, and that frees memory, then you must make sure any pointers are set to zero so that when the destructor is called by delete the memory is not double freed. Double free can lead to undefined behaviour.

Best not to call destructors explicitly, really. I still haven't seen a good answer to why you would want to do that.