1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

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

Discussion in 'C++' started by Radha.sundar, Jul 9, 2009.

  1. Radha.sundar

    Radha.sundar New Member

    Joined:
    Jul 3, 2009
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    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:
    #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 a moderator: Jul 9, 2009
  2. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,287
    Likes Received:
    364
    Trophy Points:
    83
    Moved to C-C++ Forum
     
  3. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    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.
     
  4. SaswatPadhi

    SaswatPadhi ~ Б0ЯИ Τ0 С0δЭ ~

    Joined:
    May 5, 2009
    Messages:
    1,343
    Likes Received:
    55
    Trophy Points:
    0
    Occupation:
    STUDENT !
    Location:
    Orissa, INDIA
    Home Page:
    :confused: :confused: :confused:
    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.

    But the memory is marked "unallocated", though not changed.

    :iagree:
     
  5. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    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'
     
    shabbir and SaswatPadhi like this.
  6. mayjune

    mayjune New Member

    Joined:
    Jun 14, 2009
    Messages:
    817
    Likes Received:
    33
    Trophy Points:
    0
    Occupation:
    Student
    Location:
    Pune,Delhi
    Code:
        
    [LEFT]#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();                 /*[B]Error In TC = Member Identifier Expected...?[/B]*/
        cout<<"a ="<<objA.a<<"\n";
        return 1;
      }[/LEFT]
    
     
  7. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    > 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.
     
  8. Radha.sundar

    Radha.sundar New Member

    Joined:
    Jul 3, 2009
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    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?
     
  9. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    The destructor is called when you delete the object or let it go out of scope, yes.
     
  10. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    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.
     

Share This Page