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

删除含boost::scoped_ptr socket成员的对象时程序崩溃如何解决

问题根因

崩溃的核心原因是 boost::asio::io_context 生命周期短于关联的socket生命周期:
你在connect方法内部将io_context定义为栈局部变量,connect执行完成返回后,这个io_context就会被栈释放销毁,但你创建的signal_socket仍然持有该已销毁io_context的引用。后续调用disconnect执行socket的shutdown、close操作,或者socket析构时,都会访问已经失效的内存,触发未定义行为导致程序崩溃。这也符合你给出的日志特征:执行到HEY4 VAL 1之后,调用disconnect时直接崩溃,所以后续的HEY5和boost.test的测试汇总都没有输出。

同时你代码还存在几个额外的错误点:

  • 客户端socket构造时不需要传入endpoint,你当前代码socket(io_context, signal_endpoint)是将socket绑定到对应端口,属于服务端逻辑,客户端仅需要传入io_context即可,后续主动调用connect连接目标地址。
  • 第一个测试用例basis_constructor_test的校验逻辑错误:构造函数里初始化state为CL_UNCON,但测试用例判断等于CL_READY,该用例本身就无法通过。
  • disconnect里的shutdown、close调用没有捕获错误或传入error_code参数,若socket已经处于半关闭状态,调用这两个接口会直接抛出异常导致程序终止。
修复步骤
  1. 将io_context改为SimpleClient类的成员变量,保证其生命周期和signal_socket完全一致:
class SimpleClient{
private:
    boost::asio::io_context io_context; // 新增成员变量
    boost::scoped_ptr<boost::asio::ip::tcp::socket> signal_socket; 
protected: 
    ClientState state;
// 其余接口保持不变
};
  1. 修改connect方法里的socket构造逻辑,移除构造时传入的endpoint参数:
// 原代码:signal_socket.reset(new boost::asio::ip::tcp::socket(io_context, signal_endpoint));
// 修改为:
signal_socket.reset(new boost::asio::ip::tcp::socket(io_context));
  1. 修改disconnect方法,增加错误码参数避免异常抛出:
void SimpleClient::disconnect() {
    if(signal_socket!=NULL && signal_socket->is_open()) {
        boost::system::error_code ec;
        signal_socket->shutdown(boost::asio::socket_base::shutdown_both, ec);
        // 忽略shutdown错误,继续执行close
        signal_socket->close(ec);
        signal_socket.reset();
    }
    state = ClientState::CL_UNCON;
}
  1. 修正第一个测试用例的校验逻辑,和构造函数的初始化值对齐。

完成上述修改后,socket关联的io_context在对象销毁前始终有效,就不会出现访问失效内存的崩溃问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 13:15:04