-2
int main(int argc, char *argv[])
{
    auto sp = std::make_shared<int>();
    auto p = sp.get();
    delete p; //here
    std::cout << *sp << std::endl;

    return 0;
}

I was hoping that the object managed by the shared_ptr sp will be deleted by the statement commented "here" but the object remains intact and is printed in the output statement.

  • Is this not working because I didn't create the object managed by the shared_ptr explicitly with the new keyword (because every new statement must have a corresponding delete statement and therefore every delete statement, an earlier corresponding new keyword?)?
  • And does this mean that pointed objects managed by shared_ptrs, created from the make_shared function are destroyed only by the shared_ptrs themselves?
octopus
  • 528
  • 3
  • 10
  • 5
    Don't use a smart pointer, and then try to manage the memory for it. That defeats the entire purpose. – sweenish Mar 26 '20 at 16:27
  • 1
    `shared_ptr` will delete the object for you. You are first dereferencing a dangling pointer and then doubly deleting the object because the destructor of `shared_ptr` also will delete the pointer. – alter_igel Mar 26 '20 at 16:28
  • C++ will gladly let you shoot yourself in the foot. The performant option for the compiler is usually to carry on and assume you didn't do anything bad. You can use tools such as sanitizers (address sanitizer in this case) to take the less performant option of detecting this sort of thing and getting a loud complaint about it from the tool. – chris Mar 26 '20 at 16:30
  • 1
    @octopus `delete` marks the memory occupied by the object as "free to be re-used" and calls the objects destructor. After `delete` you are *not allowed* (under pain of invoking UB) to ever access the object again. – Jesper Juhl Mar 26 '20 at 16:36

3 Answers3

2

The shared_ptr doesn't know you delete the pointer you got from .get(). So when the shared_ptr itself is destroyed it will also try to delete the object - leading to a double delete which is undefined behaviour. Additionally, dereferencing a pointer to a deleted object is also UB.

delete marks the memory occupied by the object as "free to be re-used" and calls the objects destructor. After delete you are not allowed (under pain of invoking UB) to ever access the object again.

Your program is simply invalid and anything the compiler may generate is allowed.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
  • @octopus Undefined behavior means that you have no guarantee whatsoever for the program behavior. It may seem to work, it may crash, it may give random output, anything. A crash or error is in no way guaranteed. – walnut Mar 26 '20 at 16:46
1

The way to "manage" the memory associated with a shared_ptr is to use C++ scoping, often referred to RAII (Resource Acquisition Is Initialization).

For your code:

int main(int argc, char *argv[])
{
    {
       auto sp = std::make_shared<int>();
       std::cout << *sp << std::endl;
    }
    // memory is now delete'd because "sp" is out-of-scope

    return 0;
}

With shared_ptr things can actually be (quite a bit) more complicated than that as multiple shared_ptrs can be pointing to the same memory; only when the last one is gone is the memory deleted.

Your preference should be to use std::unique_ptr until you really need shared_ptr.

Ðаn
  • 10,934
  • 11
  • 59
  • 95
0

Firstly, if you do this your object will be deleted twice, and you'll crash if you're lucky.

Second, just because something has been deleted doesn't mean it's underlying representation is guaranteed to be invalid. You can have a situation where the memory is freed, but nothing has yet come around to overwrite what was there before.

Zuodian Hu
  • 979
  • 4
  • 9
  • 2
    (not downvoter) Probably because your answer could be misleading in that you make it seem that reading deleted memory may be allowed. It is never allowed to access deleted memory. – walnut Mar 26 '20 at 16:51