0

Can someone enlighten me in what is happening here?

int* stackint = new int(5);

{
    std::unique_ptr<int> myInt(stackint);    
    *myInt = 8;

}

std::cout << *stackint; // 0

What exactly is happening here? I understand smart pointers when you construct them with new, or make_unique, what happens when you pass stack pointers to their constructor?

  • 1
    You're invoking undefined behavior by dereferencing a dangling pointer. You didn't pass a "stack pointer" either. That would be `int x = 5, *stackint = &x;` and would frankly be even worse (if there were such a thing). Your initializing a `std::unique_ptr` with an address from a previous dynamic allocation, effectively saying "take ownership of this" (which it did, and then destroyed) – WhozCraig Feb 11 '20 at 23:26
  • 2
    Very similar [question](https://stackoverflow.com/questions/54414334/transferring-ownership-of-raw-pointer-to-unique-ptr) – 1201ProgramAlarm Feb 11 '20 at 23:27
  • So when the unique_ptr goes out of scope, `stackint` becomes a dangling pointer. Also by stack pointer, I meant a pointer which is allocated on the stack, which I am definitely passing, aren't I? –  Feb 11 '20 at 23:28
  • 2
    The pointer itself is automatic; the memory it points to is not. – WhozCraig Feb 11 '20 at 23:29
  • what does it mean for a pointer to be automatic? I have not heard this term before. –  Feb 11 '20 at 23:31
  • 1
    @Iza It is the technically correct terminology for what you probably mean when you say "*stack*": https://stackoverflow.com/questions/9181782/why-are-the-terms-automatic-and-dynamic-preferred-over-the-terms-stack-and – walnut Feb 11 '20 at 23:34
  • Wo00t. Thanks @walnut . I now have another useful link in my favorites list. I'm sick of writing the same comment explaining that over and over. – user4581301 Feb 11 '20 at 23:38

2 Answers2

5

Here's an annotation:

int* stackint = new int(5);   // an int is allocated on the heap, and set to 5
{
   std::unique_ptr<int> myInt(stackint);  // myInt takes ownership of the allocation
   *myInt = 8;  // The value 5 is overwritten by 8
}  // myInt goes out of scope, its destructor deletes the heap allocation        

std::cout << *stackint; // undefined behavior:  attempt to read from already-freed memory
Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
1

The code has undefined behavior.

std::unique_ptr<int> myInt(stackint); constructs a unique_ptr owning the object that stackint points to. What storage type the pointer itself has is not relevant, only its value is passed to the constructor and the value is pointing to an int object created by a call to new, meaning that this int object has dynamic storage duration.

myInt's destructor is then called at the end of the block (}) and deletes the int object that it managed and that stackint was still pointing to, meaning that stackint's value now is an invalid pointer value.

You then dereference that invalid pointer value with *stackint, which causes undefined behavior.

walnut
  • 21,629
  • 4
  • 23
  • 59
  • Additional reading: [What is ownership of resources or pointers?](https://stackoverflow.com/questions/49024982/what-is-ownership-of-resources-or-pointers) – user4581301 Feb 11 '20 at 23:40