7

I have a std::weak_ptr. Before attempting to use the underlying object, I lock it in order to get a shared_ptr:

auto foo_sharedptr = foo_weakptr.lock();
if (foo_sharedptr != nullptr)
{
    // do stuff with foo
}

Usually this works fine. However, sometimes I get an access violation during the call to lock:

Unhandled exception at 0x00007FF91F411BC3 (My.dll) in My.exe:  
0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.

My guess is that the underlying pointer has been deleted, but my understanding of weak_ptr is that in this case, lock should return a nullptr. Am I misusing the type? If not, how should I approach debugging this?

Praetorian
  • 106,671
  • 19
  • 240
  • 328
Justin R.
  • 23,435
  • 23
  • 108
  • 157
  • 1
    Not answering why the access violation happens, but you can use [`foo_weakptr.expired()`](http://en.cppreference.com/w/cpp/memory/weak_ptr/expired) – Appleshell Aug 13 '14 at 17:53
  • If you look at http://www.boost.org/doc/libs/1_36_0/boost/weak_ptr.hpp, there is a note about access violation, is that related ? – BlueTrin Aug 13 '14 at 18:01
  • @Appleshell, the spec states that expired() is effectively called by lock(): "Effectively returns expired() ? shared_ptr() : shared_ptr(*this), executed atomically. " – Justin R. Aug 13 '14 at 18:03
  • 1
    @BlueTrin I think what they're saying here is that a ctor they're _not_ using can result in an access violation. I'm not using Boost though, so maybe my implementation has this problem. I hope not! Thanks. – Justin R. Aug 13 '14 at 18:04
  • I woulds guess that you've clobbered `foo_weakptr`, overwriting it with all-1 bits, so the access of the shared counter object fails. You'll need to look at machine code before the actual faulting instruction to see where it is getting the 0xff..ff address – Chris Dodd Aug 13 '14 at 19:05

1 Answers1

1

EDIT: Although upvoted, this does not seem to be correct answer, sorry:

http://en.cppreference.com/w/cpp/memory/shared_ptr/operator_cmp

template< class T >
bool operator==( const shared_ptr<T>& lhs, std::nullptr_t rhs );
    (7)     (since C++11)
template< class T >
bool operator!=( const shared_ptr<T>& lhs, std::nullptr_t rhs );
    (9)     (since C++11)

7) !lhs
9) (bool)lhs

....broken implementation?? Really don't know.


Test with gcc -std=c++11: (taken from http://en.cppreference.com/w/cpp/memory/weak_ptr and adapted)

#include <iostream>
#include <memory>

std::weak_ptr<int> gw;

void f()
{
    auto spt = gw.lock();
    if (spt != nullptr) {
        std::cout << *spt << "\n";
    }
    else {
        std::cout << "gw is expired\n";
    }
}

int main()
{
    {
        auto sp = std::make_shared<int>(42);
        gw = sp;
        f();
    }

    f();
}

Output as expected:

42
gw is expired

Must be elsewhere


Original:

In short: check it as bool, do not compare to nullptr (that will try lhs.get() == rhs.get() which fails with rhs = shared_ptr on nullptr):

auto foo_sharedptr = foo_weakptr.lock();
if (foo_sharedptr)
{
    // do stuff with foo
}

See the documentation:

#include <iostream>
#include <memory>
#include <thread>

void observe(std::weak_ptr<int> weak) 
{
    std::shared_ptr<int> observe(weak.lock());
    if (observe) {
        std::cout << "\tobserve() able to lock weak_ptr<>, value=" << *observe << "\n";
    } else {
        std::cout << "\tobserve() unable to lock weak_ptr<>\n";
    }
}

int main()
{
    std::weak_ptr<int> weak;
    std::cout << "weak_ptr<> not yet initialized\n";
    observe(weak);

    {
        std::shared_ptr<int> shared(new int(42));
        weak = shared;
        std::cout << "weak_ptr<> initialized with shared_ptr.\n";
        observe(weak);
    }

    std::cout << "shared_ptr<> has been destructed due to scope exit.\n";
    observe(weak);
}
firda
  • 3,268
  • 17
  • 30
  • 2
    The behaviour of `== nullptr` and the conversion to `bool` is the same (unless there's a bug in the StdLib implementation). `operator bool` is defined in terms of `get() != 0`. – dyp Aug 13 '14 at 17:48
  • I tried checking for `if (foo_sharedptr)`, but am sometimes getting the same exception. – Justin R. Aug 13 '14 at 18:01