c++ - 从继承自 std::enable_shared_from_this 的类继承后的 std::bad_weak_ptr

标签 c++ c++20 shared-ptr smart-pointers weak-ptr

我有以下代码:

#include <memory>

class A: public std::enable_shared_from_this<A> {};

struct B: public A, public std::enable_shared_from_this<B> {
    std::shared_ptr<B> get() {        
        return enable_shared_from_this<B>::shared_from_this();
    }
};

int main(){
    auto b = std::make_shared<B>();
    auto p = b->get();
}   

使用 clang (15.0.0) 和 gcc (12.2) 进行编译,并运行它会导致 std::bad_weak_ptr 异常。我很好奇为什么会这样。谢谢。

-std=c++20 -O2 -Wall -fsanitize=address
terminate called after throwing an instance of 'std::bad_weak_ptr'
  what():  bad_weak_ptr
AddressSanitizer:DEADLYSIGNAL
=================================================================
==1==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x7f0e60632941 bp 0x7f0e607fd780 sp 0x7ffdb646eee0 T0)
==1==The signal is caused by a READ memory access.
==1==Hint: this fault was caused by a dereference of a high value address (see register values below).  Disassemble the provided pc to learn which register was used.
    #0 0x7f0e60632941 in abort (/lib/x86_64-linux-gnu/libc.so.6+0x22941)
    #1 0x7f0e60a1ba48  (/opt/compiler-explorer/gcc-12.2.0/lib64/libstdc++.so.6+0xa9a48)
    #2 0x7f0e60a27079  (/opt/compiler-explorer/gcc-12.2.0/lib64/libstdc++.so.6+0xb5079)
    #3 0x7f0e60a270e4 in std::terminate() (/opt/compiler-explorer/gcc-12.2.0/lib64/libstdc++.so.6+0xb50e4)
    #4 0x7f0e60a27336 in __cxa_throw (/opt/compiler-explorer/gcc-12.2.0/lib64/libstdc++.so.6+0xb5336)
    #5 0x4011a3 in std::__throw_bad_weak_ptr() /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/shared_ptr_base.h:96
    #6 0x4011a3 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count(std::__weak_count<(__gnu_cxx::_Lock_policy)2> const&) /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/shared_ptr_base.h:1245
    #7 0x4011a3 in std::__shared_ptr<B, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<B, void>(std::__weak_ptr<B, (__gnu_cxx::_Lock_policy)2> const&) /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/shared_ptr_base.h:1548
    #8 0x4011a3 in std::shared_ptr<B>::shared_ptr<B, void>(std::weak_ptr<B> const&) /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/shared_ptr.h:381
    #9 0x4011a3 in std::enable_shared_from_this<B>::shared_from_this() /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/shared_ptr.h:935
    #10 0x4011a3 in B::get() /app/example.cpp:7
    #11 0x4011a3 in main /app/example.cpp:13
    #12 0x7f0e60634082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
    #13 0x4016cd in _start (/app/output.s+0x4016cd)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib/x86_64-linux-gnu/libc.so.6+0x22941) in abort
==1==ABORTING

最佳答案

enable_shared_from_this可以通过各种 shared_ptr 来工作构造函数 - 但前提是它是指针传递给 shared_ptr 的类的明确且可访问的基类构造函数。在您的示例中,enable_shared_from_this基础不明确。

[util.smartptr.shared.const]/1 In the constructor definitions below, enables shared_from_this with p, for a pointer p of type Y*, means that if Y has an unambiguous and accessible base class that is a specialization of enable_shared_from_this (20.11.6), then remove_cv_t<Y>* shall be implicitly convertible to T* and the constructor evaluates the statement:

if (p != nullptr && p->weak_this.expired())
  p->weak_this = shared_ptr<remove_cv_t<Y>>(*this, const_cast<remove_cv_t<Y>*>(p));

强调我的。

关于c++ - 从继承自 std::enable_shared_from_this 的类继承后的 std::bad_weak_ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75205350/

相关文章:

c++ - 递归在C++中的循环内不起作用

c++ - 比较对象指针

c++ - std::reference_wrapper 与 std::shared_ptrs 并行

c++ - 从未调用过的重载函数模板

c++ - 测试 Lua 数是整数还是 float

c++ - 在 `[likely]]` 语句中正确使用 C++20/`[[unlikely]]` `switch`

c++ - range-v3 可以包含初始化列表上的工作吗?

c++ - 在嵌套需求中,为什么使用 `requires bool_constant<X>::value;` 而不是 `requires X;` ?

请求从 C++ 到非标量类型的转换

c++ - 在构造函数之后初始化 boost::asio 套接字