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

VS2022中std::future<T>::get()触发运行时错误的原因排查

std::promise多次调用set_value导致abort()异常分析(C++20 VS2022)

你在C++20中使用std::promise和std::future结合std::jthread获取素数计算结果时,第二次迭代调用is_prime.get()触发运行时abort()错误,第一次迭代正常输出3。

问题代码

void IsPrime(uint64_t check, std::promise<bool> is_prime)
{
    if (check == 2)
        is_prime.set_value(true);
    if (check < 2 ||
        (check % 2 == 0) ||
        (check % 5 == 0))
        is_prime.set_value(false);

    for (uint64_t chase = 3; chase <= sqrt(check); chase += 2)
        if (check % chase == 0)
            is_prime.set_value(false);

    is_prime.set_value(true);
}

int main()
{
    for (int i = 3; i < 100; i += 2)
    {
        std::promise<bool> prime_promise;
        std::future<bool> is_prime = prime_promise.get_future();
        std::jthread prime_thread =
            std::jthread(IsPrime, i, std::move(prime_promise));

        if (is_prime.get())
            std::cout << i << std::endl;
    }

    return 0;
}

问题根源

std::promise的核心规则是:每个promise对象只能调用一次set_value()/set_exception()等设置结果的方法,多次调用属于未定义行为,Visual Studio的标准库实现会直接触发abort()终止程序。

  • 第一次迭代(i=3):

    1. check==2不成立,跳过第一个if;
    2. check<2、check%2==0、check%5==0均不成立,跳过第二个if;
    3. sqrt(3)≈1.7,循环条件chase<=1.7不满足,循环不执行;
    4. 最终仅调用一次is_prime.set_value(true),符合规则,无异常。
  • 第二次迭代(i=5):

    1. check==2不成立,跳过第一个if;
    2. check%5==0成立,调用is_prime.set_value(false);
    3. sqrt(5)≈2.23,循环条件不满足,循环不执行;
    4. 继续执行到最后一行,再次调用is_prime.set_value(true),违反了promise只能设置一次结果的规则,触发abort()。

修复方案

修改IsPrime函数,确保每个promise仅被设置一次结果。以下两种方案均可实现:

方案1:用else if串联条件

void IsPrime(uint64_t check, std::promise<bool> is_prime)
{
    if (check == 2)
    {
        is_prime.set_value(true);
    }
    else if (check < 2 || (check % 2 == 0) || (check % 5 == 0))
    {
        is_prime.set_value(false);
    }
    else
    {
        bool prime = true;
        for (uint64_t chase = 3; chase <= sqrt(check); chase += 2)
        {
            if (check % chase == 0)
            {
                prime = false;
                break;
            }
        }
        is_prime.set_value(prime);
    }
}

方案2:set_value后立即return

void IsPrime(uint64_t check, std::promise<bool> is_prime)
{
    if (check == 2)
    {
        is_prime.set_value(true);
        return;
    }
    if (check < 2 || (check % 2 == 0) || (check % 5 == 0))
    {
        is_prime.set_value(false);
        return;
    }

    for (uint64_t chase = 3; chase <= sqrt(check); chase += 2)
    {
        if (check % chase == 0)
        {
            is_prime.set_value(false);
            return;
        }
    }

    is_prime.set_value(true);
}

两种方案都能保证每个std::promise仅被设置一次结果,避免触发未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:00:55