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
相关产品推荐
相关产品推荐

