You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

继承含std::enable_shared_from_this的类后触发std::bad_weak_ptr异常原因问询

为什么继承多个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=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

异常原因

核心问题在于类B同时继承了两个不同特化版本的std::enable_shared_from_this:

  1. 通过基类A间接继承std::enable_shared_from_this<A>
  2. 直接继承std::enable_shared_from_this<B>

std::enable_shared_from_this的工作逻辑是:当用std::make_shared(或对象赋值给std::shared_ptr)创建实例时,shared_ptr会自动初始化enable_shared_from_this内部的weak_ptr成员,后续shared_from_this()就是通过这个weak_ptr生成新的shared_ptr。

但C++标准明确规定,一个类不能直接或间接继承多个std::enable_shared_from_this的不同特化版本,这种场景属于未定义行为。在你的代码中,std::make_shared<B>只能初始化其中一个enable_shared_from_this的weak_ptr(此处为A基类中的enable_shared_from_this<A>成员),而B直接继承的enable_shared_from_this<B>内部的weak_ptr完全未被初始化。调用enable_shared_from_this<B>::shared_from_this()时,代码尝试从未初始化的weak_ptr构造shared_ptr,最终抛出std::bad_weak_ptr异常。

解决方法

需要确保整个继承链中只有一个std::enable_shared_from_this特化,常见方案有两种:

方案1:移除基类的enable_shared_from_this

如果A不需要单独使用shared_from_this(),可移除其enable_shared_from_this<A>继承,仅让最派生类B继承enable_shared_from_this<B>:

#include <memory>

class A {};

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

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

方案2:通过基类的shared_from_this()转换类型

如果A必须保留enable_shared_from_this<A>,则B无需再继承enable_shared_from_this<B>,而是通过static_pointer_cast将A的shared_ptr转换为B的shared_ptr:

#include <memory>

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

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

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

内容的提问来源于stack exchange,提问作者Rish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 02:15:26