提问人:Atacan 提问时间:5/27/2023 更新时间:5/27/2023 访问量:147
如何修复此代码中的“在没有活动异常的情况下终止调用”错误?
How to fix "terminate called without an active exception" error in this code?
问:
首先,我是一名学生,所以代码可能不是一个高效或写得很好的代码。对不起。但是,如果它不打扰您,我可以使用一些帮助。
以下是我在主程序中使用的主程序和musical_chairs函数。
void musical_chairs(IntQueueHW6 &my_queue, unsigned int idx,unsigned int remaining_player_num, vector<int> &players)
{
this_thread::sleep_until(chrono::system_clock::now() + chrono::seconds(2));
mtx.lock();
if(!(my_queue.isFull()))
{
my_queue.enqueue(idx);// my_queue is a queue with size of total_player_num-1
cout << "Player " << idx << " captured a chair at ";
current_time();
cout << "." << endl;
}
else
//**************** I believe this block causing the error *******************
not_capture(idx);
for(int k = 0; k < remaining_player_num; k++)
{
if(players[k] == idx)
{
players.erase(players.begin()+k);
break;
}
}
}
mtx.unlock();
//*************** I believe this block causing the error **********************
}
int main()
{
unsigned int total_player_num, total_round_num, remaining_player_num;
cout << "Welcome to Musical Chairs game!" << endl << "Enter the number of players in the game: " << endl;
cin >> total_player_num;
remaining_player_num = total_player_num;
total_round_num = total_player_num - 1;
cout << "Game Start!" << endl << endl;
vector<int> players(total_player_num); // creating a vector consists of players IDs
for(int i=0; i < total_player_num; i++)
{
players[i] = i;
}
while(remaining_player_num != 1) // until only one player left in te game
{
IntQueueHW6 my_queue(total_round_num); // creating a queue with size total_round_num for chair slots
vector<thread> threads(total_player_num); // create a thread vector for all players
cout << "Time is now ";
current_time();
cout << endl;
int players_length = players.size();
for(int i = 0; i < players_length; i++)
{
int idx = players[i];
threads[idx] = thread(&musical_chairs, ref(my_queue), idx, remaining_player_num, ref(players));
}
for(int i = 0; i < players_length; i++) //joining to threads
{
int idx = players[i];
if(threads[idx].joinable())
{
threads[idx].join();
}
}
display_remaining_players(players); // changing variables accordingly
remaining_player_num --;
total_round_num -- ;
my_queue.clear();
}
unsigned int winner_id = players[0];
winner_func(winner_id); // this function displays the winner
return 0;
}
我编写了一个程序,使用多线程模拟“音乐椅”游戏。 当我运行主程序时,我收到“在没有活动异常的情况下终止调用”错误。由于我在互联网上的研究很少,这可能是因为线程超出了范围,但如果是这样,我不知道如何解决它。谁能解释一下如何解决?如果错误是由不同的事情发生的,您能解释一下吗,您能帮我修复此代码吗?提前致谢。
答:
0赞
RandomBits
5/27/2023
#1
之所以调用,是因为线程在未联接的情况下终止。std::terminate
函数中丢失的线程将自身从玩家向量中移除,但与此同时,线程继续执行,在调用 .这里缺乏同步将导致它以随机方式失败,具体取决于线程调度的变幻莫测。musical_chairs
main
join
鉴于代码结构,这将需要重新考虑才能修复。以下是我能想到的最简单的实现。它使用而不是哪个更有效率。std::atomic
std::mutex
一些简短的说明:
- 我为玩家选择了 a 而不是 a,因为玩家 ID 是唯一的,从集合中删除元素比从向量中删除元素要容易得多,效率也高得多。
std::set
std::vector
- 为了让游戏更公平,我选择线程作为每一轮的输家——否则,最后一个线程输得太频繁了。
middle
- 线程创建的 lambda 捕获是微妙的。必须按值捕获,以便每个线程都有自己的玩家 ID,但需要通过引用捕获 、 和 ,因为它们都是跨线程共享的。
pid
queue
chairs
loser
示例代码
#include <chrono>
#include <iostream>
#include <mutex>
#include <queue>
#include <set>
#include <thread>
#include <vector>
using std::cin, std::cout, std::endl;
using namespace std::chrono_literals;
using PlayerId = int;
using Queue = std::queue<PlayerId>;
using Players = std::set<PlayerId>;
int main(int argc, const char *argv[]) {
int initial_number_players{};
cin >> initial_number_players;
Players players;
for (auto i = 0; i < initial_number_players; ++i)
players.insert(i);
while (players.size() > 1) {
Queue queue;
std::vector<std::thread> threads;
std::atomic<int> chairs{}, loser{};
for (auto pid : players) {
threads.emplace_back([&,pid]() {
std::this_thread::sleep_for(250ms);
auto cid = chairs.fetch_add(1);
if (cid == players.size() / 2)
loser = pid;
});
}
for (auto& th : threads)
if (th.joinable())
th.join();
cout << "Player " << loser << " did not capture a chair" << endl;
players.erase(loser);
}
cout << "Player " << *players.begin() << " won" << endl;
return 0;
}
输出
Player 8 did not capture a chair
Player 0 did not capture a chair
Player 1 did not capture a chair
Player 2 did not capture a chair
Player 6 did not capture a chair
Player 3 did not capture a chair
Player 5 did not capture a chair
Player 4 did not capture a chair
Player 9 did not capture a chair
Player 7 won
上一个:while 循环中的命令数
下一个:终止子进程的子进程
评论
else
my_queue.clear();
-- 奇怪的是,你在循环的末尾有这个,when 是一个局部变量,每次循环迭代时都会被销毁。while
my_queue