9

I'm using a library which export a function like:

// there is some type T
std::shared_ptr<T> foo(params);

and while the following code works fine:

auto p = foo(params);
auto & v0 = *p;
// use v0 as a T's reference

the below crashes:

auto & v1 = *foo(params);
// use v1 as a T's reference

So what is the difference between v0 and v1? Many thanks for any help.

Ta Thanh Dinh
  • 638
  • 1
  • 5
  • 12

3 Answers3

11

The object pointed at by a shared_ptr exists only as long as there is at least one shared pointer alive that still points at it.

In your example there is likely only one such pointer, and it's returned by foo.

For v0, p becomes the shared_ptr keeping the object alive.

For v1, there is only a temporary shared pointer that exists only for the duration of v1's initialization. The pointer and object being pointed at are gone by the time you use the reference, making it a dangling one at the point of use.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
3

The statement

auto & v1 = *foo(params);

is a potential undefined behavior.

The function foo probably construct a std::shared_ptr inside and returns it to the caller as a temporary object (technically a prvalue) which is supposed to be assigned to some variable.

You don't assign the smart pointer of your expression to any variable. However, you grab the object pointed by (using the * operator) and assign it to the reference v1.

At the end of the expression evaluation the temporary std::shared_ptr will be destroyed and (being a smart pointer) the object pointed as well.

Therefore, auto & v1 is referring to a destroyed object and accessing to it is an undefined behavior (producing a segmentation fault in the majority of cases).

BiagioF
  • 9,368
  • 2
  • 26
  • 50
1

In your first example, p remains in scope, holding a reference to the object and thereby keeping it alive. In your second example, the shared_ptr is destroyed after v1 is created, which destroys the object (assuming it was the only reference) and leaving v1 pointing to unallocated memory.

Sneftel
  • 40,271
  • 12
  • 71
  • 104