Blue7
Blue7

Reputation: 2044

c++ std::weak_ptr to stack object

I need a pointer to a stack object that might go out of scope. I have been told that a weak pointer can achieve this, but the following code throws a seg fault:

#include <memory>
#include <cassert>
int main()
{

    std::weak_ptr<int> wp;

    {
        auto a = 4;

        wp = std::shared_ptr<int>(&a, [](auto){});
        assert(*wp.lock().get() == 4);
    }

    assert(wp.lock().get() == nullptr);

    return 0;
}

Why is this?

edit

I have found a solution that seems to work.

std::weak_ptr<int> wp;

{
    auto a = 4;

    auto sp = std::shared_ptr<int>(&a, [](auto){});
    wp = sp;
    assert(*wp.lock().get() == 4);
}

assert(wp.lock().get() == nullptr);

But a commenter has told me this is undefined behavior. Why does this work, and why is it UB?

edit2

Another commenter has said that it is because the shared pointer stays in scope, but if that is the case, why does this still work?

std::weak_ptr<int> wp;

{
    auto a = 4;
    auto sp = std::shared_ptr<int>();

    {
        sp = std::shared_ptr<int>(&a, [](auto){});
        wp = sp;
        assert(*wp.lock().get() == 4);
    } //shared pointer out of scope

    assert(*wp.lock().get() == 4);

} // stack object out of scope

assert(wp.lock().get() == nullptr);

Upvotes: 0

Views: 772

Answers (1)

Andrey Semashev
Andrey Semashev

Reputation: 10614

The problem is in these two lines of code:

wp = std::shared_ptr<int>(&a, [](auto){});
assert(*wp.lock().get() == 4);

Here you create a std::shared_ptr, initialize wp from it and immediately destroy the std::shared_ptr. At the point of assert wp is already expired and lock() returns a null std::shared_ptr. Dereferencing a null pointer leads to undefined behavior.

Other than the above, the general approach is workable:

{
    auto a = 4;

    auto sp = std::shared_ptr<int>(&a, [](auto){}); // create a shared_ptr and keep it
    wp = sp; // initialize weak_ptr from it
    assert(*wp.lock().get() == 4); // sp is still alive, so wp.lock().get() != nullptr
}

Upvotes: 2

Related Questions