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

C++类方法执行时智能指针提前释放对象引发崩溃的解决方案咨询

C++智能指针回调场景自销毁崩溃问题解决方案

你遇到的是C基于引用计数的智能指针的经典场景问题:回调方法执行过程中,内部操作清除了持有当前对象的最后一个shared_ptr,导致对象在方法执行完成前就被析构。Java不会触发该问题是因为JVM GC采用可达性扫描策略,执行栈上的this指针属于GC根引用,方法执行完前不会回收当前对象;而C shared_ptr计数归零就会立即销毁对象,不管方法是否还在执行。

以下是C++社区公认的成熟解决方案:

方案1:使用enable_shared_from_this延长生命周期(改动最小、最常用)

这是这类回调场景的标准解决方案,仅需两步修改:

  1. 让RemoteSystemDisconnectionHandler继承std::enable_shared_from_this模板类
  2. 在HandleDisconnection方法第一行获取自身的shared_ptr临时引用,拉高引用计数

修改后的核心代码:

// 继承enable_shared_from_this模板
class RemoteSystemDisconnectionHandler : public DisconnectionHandler, public std::enable_shared_from_this<RemoteSystemDisconnectionHandler>
{
 public:
  explicit RemoteSystemDisconnectionHandler(const std::shared_ptr<Closeable>& closeable_remote_system,
                                            Notifier* notifier)
      : closeable_remote_system_(closeable_remote_system), notifier_(notifier) {}

  ~RemoteSystemDisconnectionHandler() { printf("Destructed.\n"); }

  void HandleDisconnection() override {
    // 第一行先获取自身引用,引用计数+1,方法执行完前不会被销毁
    auto self = shared_from_this();
    this->closeable_remote_system_->Close();
    printf("Closed.\n");
    this->notifier_->OnDisconnection();
    printf("Notified.\n");
  }

 private:
  const std::shared_ptr<Closeable> closeable_remote_system_;
  Notifier* const notifier_;
};

修改后程序会正常输出:

Closed.
Disconnected.
Notified.
Destructed.

完全符合预期。

方案2:调整所有权结构

当前所有权链为RemoteSystem -> ReceiveDataEventHandler -> RemoteSystemDisconnectionHandler,清掉EventHandler就会直接释放DisconnectionHandler。可调整为RemoteSystem同时持有DisconnectionHandler的shared_ptr,避免所有权被单一节点控制:

class RemoteSystem : public Closeable
{
 public:
  void SetHandlers(const std::shared_ptr<EventHandler>& event_handler, const std::shared_ptr<DisconnectionHandler>& dis_handler) {
    this->receive_data_event_handler_ = event_handler;
    this->disconnection_handler_ = dis_handler;
  }

  void Close() override { 
    this->receive_data_event_handler_ = nullptr; 
    // DisconnectionHandler可等RemoteSystem自身销毁时再释放
  }
  // 其余逻辑不变
 private:
  std::shared_ptr<EventHandler> receive_data_event_handler_;
  std::shared_ptr<DisconnectionHandler> disconnection_handler_;
};

该方案适合所有权结构可调整的场景,更符合依赖注入的设计规范。

方案3:异步延迟释放资源

如果业务允许异步处理,可以把Close操作和资源清理丢到异步队列执行,等当前回调完全执行完成后再清理引用,也可以避免提前销毁问题。

注意事项

  • 继承enable_shared_from_this的类必须全程用shared_ptr管理实例,不能在栈上创建,否则调用shared_from_this会触发未定义行为
  • 不要在构造函数中调用shared_from_this,此时对象还未完成构造,shared_ptr引用计数未初始化

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 07:57:04