user5339769
user5339769

Reputation:

Why does this smart pointer give the correct result when its target should have been deleted?

Disclaimer: I know this is not how unique_ptr should be used, but for the sake of understanding, I would like to know what is going on here. Thank you!

Consider this function:

void foo(int* a) {
    unique_ptr<int> pointer_in_function(a);
}

And this main function:

int main(void) {
    int* myInt = new int(5);
    unique_ptr<int> pointer_in_main(myInt);

    foo(myInt);

    cout << *pointer_in_main << endl;
    cout << *pointer_in_main << endl;

    cin.get();
    return 0;
}

I consistently get the correct answer from the first cout. The second is undefined. The program sometimes crashes with a critical error on exit, but not always.

What I do not understand is why the first cout gives the correct answer consistently. Shouldn't the integer pointed to by myInt have been deleted when pointer_in_function went out of scope? Thank you for your help!

edit: As an aside, just to be sure, am I correct in my assumption that calling foo should delete my integer because pointer_in_function goes out of scope?

Upvotes: 0

Views: 70

Answers (2)

AndreyS Scherbakov
AndreyS Scherbakov

Reputation: 2778

It's not a good way to do (pure enough) experiments with constructors / destructors or deletion. If you have an object uncorrupted it DOESN'T imply that a delete operator hasn't been called (as its effect to the memory data is undefined and indeed many memory manager implementations don't change the released memory content immediately). Instead, create a class with explicit constructor(s) and destructor reporting their invocation and use it in place of int. As a destructor call prepends an object deletion (and as your code doesn't use stack or static allocation of an object under test, a destructor call is always implies a deletion), you may use destructor calls to trace deletions. Something like:

#include <iostream>
class MyObj {
    int value;
    MyObj(int v) : value(v) {std::cerr << "MyObj ctor called"<<std::endl;}
    ~MyObj() {std::cerr << "MyObj dtor called"<<std::endl;}
};

.....
int main (int argc, char **argv) {
    MyObj* myInt = new MyObj(5);
....
}

Upvotes: 1

user743382
user743382

Reputation:

What I do not understand is why the first cout gives the correct answer consistently.

Most implementations do not clear memory after deleting or return it back to the OS, so if you inspect the memory quickly after deleting, the chances of it not having been overwritten yet are higher.

That's one of the valid consequences of undefined behaviour. It may be 100% predictable on your particular implementation, though it need not behave the same on others.

Upvotes: 5

Related Questions