Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can a method called from an object delete the object?

I’m having a bit of confusion trying to understand what’s happening here.
If a class object calls a method which then in tern destroys the object, then the method should never return and the object should be destroyed right away and the destructor be called immediately.. Right? But instead the code just crashes.. So is an object not allowed to a call a method to delete itself? I’m assuming from how the callstack works, the pointer to the object would be destroyed hence when the function returns back to the caller the pointer is no longer valid when invoking further down the callstack?

class Foo
{
public:
    virtual void Run()
    {
        printf("Entering callback\n");
        RunSomeCallback();
        printf("We're back from callback\n");
    }
    virtual void RunSomeCallback() = 0;
    
    virtual ~Foo()
    {
        printf("We're Destroyed\n");
    }
};

Foo* f = nullptr;

void DestroyFoo();

class Bar : public Foo
{
public:
    virtual void RunSomeCallback()
    {
        printf("Inside callback\n");
        DestroyFoo();
    }
};


void DestroyFoo()
{
    printf("Deleting foo\n");
    delete f;
}
int main()
{
    f = new Bar();
    f->Run();
    return 0;
}

Then the behavior seems to change when I run the code with shared_ptr, but in this case the destructor is called before it prints "We’re back from callback", the code runs but is that then undefined behavior?

class Foo
{
public:
    virtual void Run()
    {
        printf("Entering callback\n");
        RunSomeCallback();
        printf("We're back from callback\n");
    }
    virtual void RunSomeCallback() = 0;
    
    virtual ~Foo()
    {
        printf("We're Destroyed\n");
    }
};

std::shared_ptr<Foo> f;

void DestroyFoo();

class Bar : public Foo
{
public:
    virtual void RunSomeCallback()
    {
        printf("Inside callback\n");
        DestroyFoo();
    }
};


void DestroyFoo()
{
    printf("Deleting foo\n");
    f = nullptr;
}
int main()
{
    f = std::make_shared<Bar>();
    f->Run();
    return 0;
}

Order of prints

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Entering callback
Inside callback
Deleting foo
We're Destroyed
We're back from callback

So is the object not actually destroyed until all its methods are complete?

>Solution :

There is no problem with an object being destroyed while a member function is still executing on it (regardless of where in the call stack).

However, after the object’s lifetime has ended with the destructor call inoked from delete, no function, not even the member function that is still running, may access any member of the object and the memory used by the object may be reused by other objects as well. (Technically it is also implementation-defined whether reading this at all is still allowed, but practically that is fine as long as this isn’t dereferenced anymore.)

In your example code no members are accessed after delete (including the destructor) is called, so the program has defined behavior and the output you gave is expected. The destructor is called by delete, ending the objects lifetime, and then Foo::Run continues execution without ever touching the object again.

That’s true for both code snippets. Setting the std::shared_ptr to nullptr is effectively also just deleteing the object.


If this causes a crash on your system, then I would suspect a compiler bug

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading