Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why I can access member functions even after the object was deleted?

I'm new to C++ and from what I learned so far when you call delete on a pointer that points to something created on the heap then whatever is pointed by that pointer gets erased and the memory is freed, right?

However when I tried this on a simple class:

class MyClass
{
    int _Id;
public:
    MyClass(int id) : _Id(id)
    {
        std::cout << "$Constructing the damn thing! " << _Id << std::endl;
    }
    ~MyClass()
    {
        std::cout << "?Destructing the damn thing! " << _Id << std::endl;
    }
    void Go_XXX_Your_Self()
    {
        std::cout << "%OooooooooO NOOOOOO! " << _Id << std::endl;
        delete this;
    }
    void Identify_Your_Self()
    {
        std::cout << "#Object number: " << _Id << " Located at: " << this << std::endl;
    }
};

These are just some stupid tests to see how delete works:

int main()
{
    MyClass* MC1 = new MyClass(100);
    MyClass* MC2 = new MyClass(200);
    MyClass* MC3 = MC2;

    std::cout << MC1 << " " << MC2 << " " << MC3 << " " << std::endl;

    MC1->Identify_Your_Self();
    MC2->Identify_Your_Self();
    MC3->Identify_Your_Self();

    delete MC1;

    MC1->Identify_Your_Self();


    MC3->Go_XXX_Your_Self();

    MC3->Identify_Your_Self();


    delete MC2;

    MC2->Identify_Your_Self();

    MC2->Go_XXX_Your_Self();

    MC2->Identify_Your_Self();

    return 0;
}

Here's the output:

$Constructing the damn thing! 100
$Constructing the damn thing! 200
0x3e3e90 0x3e3eb0 0x3e3eb0
#Object number: 100 Located at: 0x3e3e90
#Object number: 200 Located at: 0x3e3eb0
#Object number: 200 Located at: 0x3e3eb0
?Destructing the damn thing! 100
#Object number: 0 Located at: 0x3e3e90
%OooooooooO NOOOOOO! 200
?Destructing the damn thing! 200
#Object number: 4079248 Located at: 0x3e3eb0
?Destructing the damn thing! 4079248
#Object number: 4079280 Located at: 0x3e3eb0
%OooooooooO NOOOOOO! 4079280
?Destructing the damn thing! 4079280
#Object number: 4079280 Located at: 0x3e3eb0

So, my question is, why I'm still able to call Go_XXX_Your_Self() and Identify_Your_Self() even after the object was deleted?

Is this how it works in C++? (is there even after you delete it?)

Also can you check to see if it's not there? (I know theoretically is not possible but I'm curious to see what methods are out there)

like image 549
SLC Avatar asked Nov 05 '25 22:11

SLC


2 Answers

So, my question is, why I'm still able to call Go_XXX_Your_Self() and Identify_Your_Self() even after the object was deleted?

Because of undefined behavior.

Is this how it works in C++? (is there even after you delete it?)

Because of undefined behavior. There is no guarantee that it will work the same on other implementations. Again, undefined behavior.

Also can you check to see if it's not there? (I know theoretically is not possible but I'm curious to see what methods are out there)

delete MC1;
MC1 = nullptr;

By setting the pointer to nullptr after deleteing it, the runtime is most likely to detect that you are accessing an invalid, you-have-no-right-to-use location. Also, by diligently doing this for all applicable pointers, you have the ability to check if the object is valid or not (valid if non-nullptr).

if(my_ptr) {
   // my_ptr is most possibly valid (though you can still go wrong)
   // use my_ptr
}

Similarly, you should also set raw pointers to nullptr when they aren't yet initialized to some valid address.

MyClass* some_ptr = nullptr;
...

But again, if you have access to modern C++11 facilities, it's much better not to use raw pointers at all, and just use std::unique_ptr or std::shared_ptr (depending on your required semantics). And on future C++ standard revisions, you may also want to use the proposed std::exempt_ptr which is a non-owning, observe-only pointer wrapper.

like image 141
Mark Garcia Avatar answered Nov 08 '25 14:11

Mark Garcia


When you call delete on an object, the memory used by that object is made available to use by another use of new (or, really, by anything that uses the heap). Until such time, the deleted object may (or may not) retain its previous value. But eventually, as your program goes on running, the memory used by the deleted object will be overwritten, and then bad things will happen if you're lucky: your program will crash on you. If you're unlucky, you program will not crash until it is deployed in the field.

like image 43
zentrunix Avatar answered Nov 08 '25 14:11

zentrunix