从继承自std::enable_shared_from_this的类继承后的std::bad_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在下面的构造函数定义中,对于类型为Y*的指针p,启用shared_from_thisp,意味着如果Y具有明确且可访问的基类,该基类是enable_shared_from_this(20.11.6)的专用化,则CCD_ 12应隐式转换为CCD_

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

强调矿。

最新更新