【问题标题】:Why am I getting an access violation when locking a weak_ptr?为什么我在锁定weak_ptr 时会出现访问冲突?
【发布时间】:2014-08-13 17:31:08
【问题描述】:

我有一个 std::weak_ptr。在尝试使用底层对象之前,我将其锁定以获取 shared_ptr:

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

通常这可以正常工作。但是,有时我在调用 lock 期间遇到访问冲突:

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

我的猜测是底层指针已经被删除了,但是我对weak_ptr的理解是,在这种情况下,lock应该返回一个nullptr。我在滥用类型吗?如果没有,我应该如何进行调试?

【问题讨论】:

  • 不回答为什么会发生访问冲突,但你可以使用foo_weakptr.expired()
  • 如果你看boost.org/doc/libs/1_36_0/boost/weak_ptr.hpp,有一个关于访问冲突的注释,有关系吗?
  • @Appleshell,规范声明 expired() 被 lock() 有效调用:“有效返回 expired() ? shared_ptr() : shared_ptr(*this), 执行原子地。”
  • @BlueTrin 我认为他们在这里所说的是他们使用的 ctor 可能会导致访问冲突。我没有使用 Boost,所以也许我的实现有这个问题。我希望不是!谢谢。
  • 我猜你已经破坏了foo_weakptr,用全1位覆盖它,所以共享计数器对象的访问失败。您需要在实际的错误指令之前查看机器代码,以查看它从哪里获得 0xff..ff 地址

标签: c++ c++11 access-violation unhandled-exception weak-ptr


【解决方案1】:

编辑:虽然赞成,但这似乎不是正确的答案,抱歉:

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

.... 执行失败??真的不知道。


使用 gcc -std=c++11 进行测试:(取自 http://en.cppreference.com/w/cpp/memory/weak_ptr 并改编)

#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();
}

按预期输出:

42 gw过期了

必须在其他地方


原文:

简而言之:将其检查为 bool,不要与 nullptr 进行比较(这将尝试 lhs.get() == rhs.get() 失败,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);
}

【讨论】:

  • == nullptr 的行为和到bool 的转换是相同的(除非在 StdLib 实现中存在错误)。 operator bool 是根据 get() != 0 定义的。
  • 我尝试检查 if (foo_sharedptr),但有时会遇到同样的异常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多