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

Boost Cobalt+Asio异常问题:无效主机未按预期抛出异常

Boost Cobalt+Asio解析无效主机时异常未被捕获导致进程终止

问题现象

  • 解析有效主机URL时,代码运行正常;
  • 解析无效主机URL时,预期异常会被catch块捕获,但实际未进入捕获逻辑,而是输出错误信息并触发SIGABRT终止进程。

相关代码

#include <boost/cobalt.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

#include <iostream>
#include <string>
#include <vector>

namespace net               = boost::asio;
namespace cobalt            = boost::cobalt;
using executor_type         = cobalt::executor;

cobalt::task<std::vector<net::ip::tcp::endpoint>> resolve(
    executor_type executor,
    std::string const& hostname,
    std::string const& service
)
{
    auto endpoints = std::vector<net::ip::tcp::endpoint>{};
    auto resolver = net::ip::tcp::resolver{executor};
    try
    {
        auto results = co_await resolver.async_resolve(
            hostname,
            service,
            cobalt::use_op);

        for (const auto& result : results)
            endpoints.push_back(result.endpoint());

        co_return endpoints;
    }
    catch (...)
    {
        std::cerr << "Resolve exception\n";
        throw;
    }
}

cobalt::task<void> main2()
{
    auto executor = co_await cobalt::this_coro::executor;

    auto endpoints = co_await resolve(executor, "www.googleqqq.com", "https"); // 故意设置无效主机,改为www.google.com可正常运行

    // 打印解析后的端点
    for (const auto& endpoint : endpoints)
        std::cerr << endpoint << std::endl;

    co_return;
}

int main()
{
    try
    {
        net::io_context ctx;
        cobalt::spawn(ctx, main2(), net::detached);
        ctx.run();
    }
    catch (...)
    {
        std::cerr << "Uncaught exception\n";
    }
    return 0;
}

CMakeLists.txt配置

注:为避免强制用户在系统安装Boost,使用了FetchContent,首次编译会耗时几分钟。
注:需要提前安装OpenSSL。

cmake_minimum_required(VERSION 3.30)
project(async_resolve_exception_issue)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include(FetchContent)

# OpenSSL
find_package(OpenSSL REQUIRED)

# Boost
FetchContent_Declare(
    boost
    GIT_REPOSITORY https://github.com/boostorg/boost.git
    GIT_TAG boost-1.85.0
    GIT_SHALLOW TRUE
    GIT_PROGRESS TRUE
    OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(boost)
find_package(Boost 1.85 REQUIRED COMPONENTS system)

add_executable(${PROJECT_NAME}
    ${PROJECT_NAME}.cpp
)
target_link_libraries(${PROJECT_NAME}
    PUBLIC
        Boost::beast
        Boost::cobalt
        OpenSSL::SSL
        OpenSSL::Crypto
)

执行命令

build/async_resolve_exception_issue 

错误信息

libc++abi: terminating due to uncaught exception of type boost::detail::with_throw_location<boost::system::system_error>: Host not found (authoritative) [asio.netdb:1]

运行环境

  • MacOS Sonoma(14.6)
  • cmake 3.30.2
  • clang 18.1.8

问题原因及解决方法

问题根源在于使用cobalt::spawn时传入了net::detached参数:

  • 当协程以detached模式运行时,协程内部未捕获的异常会直接调用std::terminate()终止进程,无法传递到main函数的catch块中。

解决方法1:捕获协程内的异常

在main2协程中直接捕获resolve抛出的异常,避免异常扩散到detached协程外:

cobalt::task<void> main2()
{
    auto executor = co_await cobalt::this_coro::executor;

    try {
        auto endpoints = co_await resolve(executor, "www.googleqqq.com", "https");
        for (const auto& endpoint : endpoints)
            std::cerr << endpoint << std::endl;
    } catch(const std::exception& e) {
        std::cerr << "解析失败:" << e.what() << std::endl;
        // 可根据需求处理异常,无需重新抛出
    }

    co_return;
}

解决方法2:避免使用detached模式,获取协程结果

修改main函数,不使用detached,而是通过task.get()获取协程结果,此时异常会被传递到main的catch块:

int main()
{
    try
    {
        net::io_context ctx;
        auto coro_task = cobalt::spawn(ctx, main2());
        ctx.run();
        coro_task.get(); // 触发协程中未捕获的异常
    }
    catch (const std::exception& e)
    {
        std::cerr << "捕获到异常:" << e.what() << std::endl;
    }
    return 0;
}

解决方法3:自定义detached协程的异常处理

如果必须使用detached模式,可以通过cobalt::spawn的重载版本传入异常处理函数:

void handle_coro_exception(std::exception_ptr e)
{
    try {
        if (e) std::rethrow_exception(e);
    } catch(const std::exception& ex) {
        std::cerr << "协程异常处理:" << ex.what() << std::endl;
    }
}

int main()
{
    net::io_context ctx;
    cobalt::spawn(ctx, main2(), cobalt::detached, handle_coro_exception);
    ctx.run();
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:44:54