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

C++ Promise与Future触发std::bad_alloc错误,请求代码问题排查

排查std::bad_alloc错误及多线程Minimax实现问题

核心问题分析

1. Promise对象的悬空引用

循环中创建的prms是局部变量,每次循环结束后该对象就会被销毁,但线程通过ref(prms)持有了它的引用。线程后续尝试调用pr.set_value()时,引用指向的是已销毁的对象,这会触发未定义行为,可能表现为std::bad_alloc或其他崩溃。

2. 棋盘对象的悬空引用

同样,循环内的nBoard是局部变量,线程通过ref(nBoard)引用它。循环结束后nBoard被销毁,线程访问已释放的内存,会导致内存访问错误,进一步引发未定义行为。

3. 潜在的Minimax内存问题

如果minimax函数本身存在内存泄漏(比如递归深度过大导致栈溢出,或反复创建大量未释放的容器),也可能触发std::bad_alloc。但需先解决前两个线程生命周期问题,再排查算法本身。

修正后的代码示例

#include <memory>

// 修改board为值传递,避免引用生命周期问题
void findValue(promise<vector<pair<int,int>>> &pr, vector<vector<int>> board, int depth, int player){
    vector<pair<int,int>> result = minimax(board, depth, player, -10000, 10000);
    pr.set_value(result);
}

void debugBoard(){
    int maxDepth = 5;
    auto board = customPosition();
    int turn = 1;
    int startTime = clock();

    vector<pair<int,int>> result;
    vector<thread> threads;
    vector<future<vector<pair<int,int>>>> futures;
    // 使用智能指针存储promise,延长生命周期
    vector<shared_ptr<promise<vector<pair<int,int>>>>> promises;

    for(int i=1;i<=maxDepth;i++){
        auto prms = make_shared<promise<vector<pair<int,int>>>>();
        promises.push_back(prms);
        futures.push_back(prms->get_future());
        auto nBoard = board;
        // 传递promise的引用(智能指针保证对象存活),board改为值传递
        threads.push_back(thread(&findValue, ref(*prms), nBoard, i, turn));
    }

    this_thread::sleep_for(chrono::seconds(5));

    int finalDepth = 0;
    for(int i=0;i<maxDepth;i++){
        if(futures[i].wait_for(chrono::seconds(0)) == future_status::ready){
            result = futures[i].get();
            finalDepth = i+1;
        }
    }

    cout<<endl<<"Result calculated up till "<<finalDepth<<" depth, and is\n";
    printInfo(result, startTime);

    for(auto& t : threads){
        t.join();
    }
    
    if(finalDepth > 0){ // 避免未找到结果时访问空result导致崩溃
        board[result[1].first][result[1].second] = board[result[0].first][result[0].second];
        board[result[0].first][result[0].second] = 0;
        printBoard(board);
    } else {
        cout << "No valid result calculated within time limit." << endl;
    }
}

关键修改说明

  • 使用shared_ptr存储promise对象,确保线程运行期间promise始终存活,避免悬空引用。
  • 将findValue的board参数改为值传递,每个线程拥有独立的棋盘副本,避免原局部变量销毁后线程访问无效内存。
  • 增加finalDepth > 0的判断,防止未计算出任何结果时访问空的result导致崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 18:57:54