Developing Windows Applications by Mykola Dudar

Helping Developers Build Applications for Windows using Visual Studio.

Calling methods of deleted object

Calling methods of deleted object

  • Comments 3

I came across an interesting discussion today. A person who asked the question called a method of C++ object after it was deleted. And it worked. I guess if I have ever attempted to do something like this, it failed for me and I have not had a chance to ask this question. Here is the code snippet (copying from email thread):

ref class Foo

{

public:

   ~Foo() { Console::WriteLine(L"Foo::~Foo"); }

   void Doit() { Console::WriteLine(L"Foo::Doit"); }

};

 

class Bar

{

public:

   ~Bar() { Console::WriteLine(L"Bar::~Bar"); }

   void Doit() { Console::WriteLine(L"Bar::Doit"); }

};

 

int main(array<System::String ^> ^args)

{

    Foo^ f = gcnew Foo();

    f->Doit();

    delete f;

    f->Doit();   // This works fine. 

    Bar* b = new Bar();

    b->Doit();

    delete b;

    b->Doit();   // This also works fine. 

    return 0;

}

Apparently the reason for why this works is that even the compiler maps the call to delete to a call to the Dispose/destructor of the object, the garbage collector may not immediately reclaim the memory. In result, it is still possible to access the managed object. Why does this work for native code? Because in this example the code of the method does not access memory or use any data member of the object. If it was, then it would fail because memory has been already released at that point of time. An example of this would be iterating though a collection of data stored in a member variable of this class. Overall behavior in this scenario (after delete is called) is undefined and anything can happen. In case of a person who asked this question, it just worked fine. And I thank him for asking good question!

  • Hello,

    > Because in this example the code of the method does not access memory or use any data member of the object

    ...and also because the method is not virtual. In other words, it works because the call does not use the 'this' pointer in any way.
    That's wht you could also write:
    Foo* f  = NULL;
    f->Doit();
  • You are absolutely right. As a matter fact exactly same argument was made on the email thread that was discussing this issue. Another example would be printing a value of member variable or anything else that require access to data allocated during call to new Class() or released when object is deleted.
  • MFC used to do this all over the place.
Page 1 of 1 (3 items)