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

使用use_future的Boost Asio异步连接偶发段错误问题排查

ASIO结合use_future实现异步Socket连接时偶发段错误问题排查

我在使用asio库结合use_future实现Socket异步连接时,代码90%的时间能正常运行,但偶尔会出现段错误。排查后发现代码会打印checkpoint 2、3,但不会打印checkpoint 4。

lldb调试得到以下信息:

Process 63910 stopped
* thread #4, stop reason = EXC_BAD_ACCESS (code=2, address=0x100072e08)
    frame #0: 0x000000010002648c XYZ`std::__1::enable_if<is_error_code_enum<asio::error::basic_errors>::value, std::__1::error_code&>::type std::__1::error_code::operator=<asio::error::basic_errors>(this=0x0000000100072e08, __e=operation_aborted) at system_error:349:20
   346              error_code&
   347          >::type
   348          operator=(_Ep __e) _NOEXCEPT
-> 349              {*this = make_error_code(__e); return *this;}
   350 
   351      _LIBCPP_INLINE_VISIBILITY
   352      void clear() _NOEXCEPT
Target 0: (XYZ) stopped.

相关代码如下:

struct Peer {
    std::string address;
    uint16_t    port;
};

class bar
{
    private:
        std::shared_ptr<asio::ip::tcp::endpoint> endpoint;
        std::shared_ptr<asio::io_context> context;
        std::shared_ptr<asio::ip::tcp::socket> socket;
    public:
        bool foo(Peer peer);
};

bool bar::foo(Peer peer) {

            endpoint = std::move(std::make_shared<asio::ip::tcp::endpoint>(asio::ip::make_address(peer.address), peer.port));

            context = std::move(std::make_shared<asio::io_context>());

            socket = std::move(std::make_shared<asio::ip::tcp::socket>(*context));

            std::chrono::milliseconds span(100);
            std::chrono::milliseconds zero_s(0);

            std::cout << "checkpoint 2" << std::endl;

            std::future<void> connect_status = socket->async_connect(*endpoint, asio::use_future);
            context->run_for(span);

            std::cout << "checkpoit 3" << std::endl;

            if (connect_status.wait_for(zero_s) == std::future_status::timeout)
                return false;
            
            std::cout << "checkpoint 4" << std::endl;

            connect_status.get();

            
}

问题原因及修复方案

经排查,问题出在对象析构顺序与构造顺序相反。当重复调用foo方法时,移动赋值操作会先销毁旧的context,而此时旧的socket还未被销毁,socket的析构函数执行时依赖的context已经超出作用域,从而引发段错误。

修正后的代码如下:

socket.reset();
            context.reset();
            endpoint.reset();

            endpoint = std::make_shared<asio::ip::tcp::endpoint>(asio::ip::make_address(peer.address), peer.port);
            context = std::make_shared<asio::io_context>();
            socket = std::make_shared<asio::ip::tcp::socket>(*context);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 08:06:05