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

使用std::async的简单C++程序为何崩溃?

代码崩溃问题分析与修复

背景

在排查AIX平台使用XLClang++时__cxa_end_catch崩溃问题的过程中,尝试重构代码以避免使用std::exception_ptr,代码如下:

#include <cstdio>
#include <exception>
#include <future>
#include <thread>
#include <vector>

std::future<std::invalid_argument> GetExceptionFromDeadThread()
{
    return std::async(std::launch::async, []() {
        try
        {
            throw std::invalid_argument("Some string long enough to allocate on the heap?                                                                                                             ");
        }
        catch (std::invalid_argument e)
        {
            return e;
        }
        catch (...)
        {
            std::fprintf(stderr, "'std::rethrow_exception(future.get())' threw unexpected exception");
            abort();
        }
    });
}

int main()
{
    try
    {
        constexpr size_t numThreads(100);
        std::vector<std::future<std::invalid_argument>> futures;

        while (true)
        {
            for (size_t i = 0; i < numThreads; ++i)
            {
                futures.push_back(GetExceptionFromDeadThread());
            }

            while (!futures.empty())
            {
                auto& future(futures.back());
                future.wait();

                try
                {
                    throw future.get();
                }
                catch (std::invalid_argument&)
                {
                    std::fputs(".", stdout);
                }
                catch (...)
                {
                    std::fprintf(stderr, "'std::rethrow_exception(future.get())' threw unexpected exception");
                    abort();
                }

                futures.pop_back();
            }
        }
    }
    catch (...)
    {
        std::fprintf(stderr, "Caught unexpected exception");
        abort();
    }
}

测试崩溃情况

在Windows开发机(Visual Studio 2022,默认创建的C++控制台项目,Debug|x64配置)测试时,程序出现崩溃,报错信息:

HEAP[exception_ptr_test.exe]: Invalid address specified to
RtlValidateHeap( 0000021A37BB0000, 00007FFFDA43A2F0 )

调用栈信息:

>   ntdll.dll!RtlpBreakPointHeap()  Unknown
    ntdll.dll!RtlpValidateHeapEntry()   Unknown
    ntdll.dll!RtlValidateHeap() Unknown
    KernelBase.dll!HeapValidate()   Unknown
    ucrtbased.dll!_CrtIsValidHeapPointer(const void * block) Line 1407  C++
    ucrtbased.dll!free_dbg_nolock(void * const block, const int block_use) Line 904 C++
    ucrtbased.dll!_free_dbg(void * block, int block_use) Line 1030  C++
    ucrtbased.dll!free(void * block) Line 32    C++
    vcruntime140d.dll!__std_exception_destroy(__std_exception_data * data) Line 46  C++
    exception_ptr_test.exe!std::exception::~exception() Line 91 C++
    exception_ptr_test.exe!std::logic_error::~logic_error() C++
    exception_ptr_test.exe!std::invalid_argument::~invalid_argument()   C++
    exception_ptr_test.exe!std::_Packaged_state<std::invalid_argument __cdecl(void)>._Call_immediate() Line 494    C++
    exception_ptr_test.exe!std::_Task_async_state<std::invalid_argument>::{ctor}::__l2::<lambda_1>::operator()() Line 664   C++
    exception_ptr_test.exe!std::invoke<`std::_Task_async_state<std::invalid_argument>::_Task_async_state<std::invalid_argument><std::_Fake_no_copy_callable_adapter<`GetExceptionFromDeadThread'::`2'::<lambda_1>>>.'::`2'::<lambda_1> &>(std::_Task_async_state<std::invalid_argument>::{ctor}::__l2::<lambda_1> & _Obj) Line 1695  C++
    exception_ptr_test.exe!std::_Func_impl_no_alloc<`std::_Task_async_state<std::invalid_argument>::_Task_async_state<std::invalid_argument><std::_Fake_no_copy_callable_adapter<`GetExceptionFromDeadThread'::`2'::<lambda_1>>>.'::`2'::<lambda_1>,void>._Do_call() Line 874   C++
    exception_ptr_test.exe!std::_Func_class<void>::operator()() Line 920    C++
    exception_ptr_test.exe!Concurrency::details::_MakeVoidToUnitFunc::__l2::<lambda_1>::operator()() Line 2363  C++
    exception_ptr_test.exe!std::invoke<`Concurrency::details::_MakeVoidToUnitFunc'::`2'::<lambda_1> &>(Concurrency::details::_MakeVoidToUnitFunc::__l2::<lambda_1> & _Obj) Line 1696    C++
    exception_ptr_test.exe!std::_Func_impl_no_alloc<`Concurrency::details::_MakeVoidToUnitFunc'::`2'::<lambda_1>,unsigned char>._Do_call() Line 878    C++
    exception_ptr_test.exe!std::_Func_class<unsigned char>::operator()() Line 921   C++
    exception_ptr_test.exe!Concurrency::task<unsigned char>::_InitialTaskHandle<void,`std::_Task_async_state<std::invalid_argument>::_Task_async_state<std::invalid_argument><std::_Fake_no_copy_callable_adapter<`GetExceptionFromDeadThread'::`2'::<lambda_1>>>.'::`2'::<lambda_1>,Concurrency::details::_TypeSelectorNoAsync>._LogWorkItemAndInvokeUserLambda<std::function<unsigned char __cdecl(void)>>(std::function<unsigned char __cdecl(void)> _func) Line 3528    C++
    exception_ptr_test.exe!Concurrency::task<unsigned char>::_InitialTaskHandle<void,`std::_Task_async_state<std::invalid_argument>::_Task_async_state<std::invalid_argument><std::_Fake_no_copy_callable_adapter<`GetExceptionFromDeadThread'::`2'::<lambda_1>>>.'::`2'::<lambda_1>,Concurrency::details::_TypeSelectorNoAsync>._Init(Concurrency::details::_TypeSelectorNoAsync __formal) Line 3548   C++
    exception_ptr_test.exe!Concurrency::task<unsigned char>::_InitialTaskHandle<void,`std::_Task_async_state<std::invalid_argument>::_Task_async_state<std::invalid_argument><std::_Fake_no_copy_callable_adapter<`GetExceptionFromDeadThread'::`2'::<lambda_1>>>.'::`2'::<lambda_1>,Concurrency::details::_TypeSelectorNoAsync>._Perform() Line 3533   C++
    exception_ptr_test.exe!Concurrency::details::_PPLTaskHandle<unsigned char,Concurrency::task<unsigned char>::_InitialTaskHandle<void,`std::_Task_async_state<std::invalid_argument>::_Task_async_state<std::invalid_argument><std::_Fake_no_copy_callable_adapter<`GetExceptionFromDeadThread'::`2'::<lambda_1>>>.'::`2'::<lambda_1>,Concurrency::details::_TypeSelectorNoAsync>,Concurrency::details::_TaskProcHandle>::invoke() Line 1475   C++
    exception_ptr_test.exe!Concurrency::details::_TaskProcHandle::_RunChoreBridge(void * _Parameter) Line 171   C++
    exception_ptr_test.exe!Concurrency::details::_DefaultPPLTaskScheduler::_PPLTaskChore::_Callback(void * _Args) Line 57   C++
    msvcp140d.dll!Concurrency::details::`anonymous namespace'::_Task_scheduler_callback(_TP_CALLBACK_INSTANCE * _Pci, void * _Args, _TP_WORK * __formal) Line 134   C++
    ntdll.dll!TppWorkpExecuteCallback() Unknown
    ntdll.dll!TppWorkerThread() Unknown
    kernel32.dll!BaseThreadInitThunk()  Unknown
    ntdll.dll!RtlUserThreadStart()  Unknown

其他线程状态

修复方法

将代码中catch (std::invalid_argument e)块内的return e改为return std::invalid_argument(e)后,崩溃问题消失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 07:54:59