Reputation: 2044
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
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