【问题标题】:Error: terminate called throwing an exceptionAbort trap: 6错误:终止调用抛出异常中止陷阱:6
【发布时间】:2012-11-21 13:00:33
【问题描述】:

我正在制作一个处理继承的烫手山芋游戏。我有土豆班、球员班和裁判班。

在我的裁判类中调用 toss 函数时,我一直收到同样的错误,我似乎无法弄清楚原因:终止调用抛出异常中止陷阱:6

我发现在 umpire::start() 中,我的 for 循环中对 Players.at(randU)->toss(*m) 的调用导致出现此错误。但在我看来一切都很好。

谁能帮帮我?谢谢!

Umpire.cc

#include <iostream>
#include <string>
#include "potato.h"
#include "player.h"
#include "umpire.h"
#include "PRNG.h"
using namespace std;

// Declare globally
int gamecount=1;

// GLOBAL VARIABLES
bool first=false; // False if set has not started
PRNG rplayer;

// UMPIRE CONSTRUCTOR-------------------------------------------------------------------
Umpire::Umpire( Player::PlayerList &players ){
   Players=players;
   cout<<"\tMashed POTATO will go off after ";
   cout.flush();
   m=new Mashed(Players.size()-1);
   cout << " tosses" << endl;
   cout.flush();
   cout <<"\tFried POTATO will go off after 5 tosses" << endl;  
   cout.flush();
   f=new Fried(5);}

// UMPIRE DESTRUCTOR-------------------------------------------------------------------
Umpire::~Umpire(){  
    delete m;
    delete f;}


// UMPIRE START------------------------------------------------------------------------
void Umpire::start(){
int randU;
int gameCount=1; // Keeps track of sets

// Check if you are at the end of the list.
if(Players.size()==1){
    // Who won?
    cout << Players.at(0)->getId() << "wins the Match!" << endl;
    cout.flush();}
else{

// Print output for sets----------------------------------------------------------------
// See which potato is being used in the set
if(gameCount%2!=0){ 
    cout << "Set " << gameCount << "-\tUser (mashed) [";
    cout.flush();}
else{ 
    cout << "Set " << gameCount << "-\tUser (fried) [";
    cout.flush();}
gameCount++; // increase gamecount
// Outputting players left in the set
for(unsigned int i=0;i<Players.size();i++){
    cout<<Players.at(i)->getId();}
cout <<"]: ";
cout.flush();

//Start Tossing--------------------------------------------------------------------------
    randU=rplayer(Players.size()-1);
    // Output A(id) or R(id)
    if (randU%2==0){
        cout<<"A("<<randU<<"), ";
        cout.flush();}
    else{
        cout<<"R("<<randU<<"), ";
        cout.flush();}
    if(first==false){
        for(unsigned int i=0; i<Players.size(); i++){
            if(Players.at(i)->getId()==Players.at(randU)->toss(*m)){
                Players.erase(Players.begin()+i);
                cout << "Eliminated: "<< i << endl;
                cout.flush();}
        }
        first=true;
        f->reset();
        start();
    }
    else{
        for(unsigned int i=0; i<Players.size(); i++){
            if(Players.at(i)->getId()==Players.at(randU)->toss(*f)){
                Players.erase(Players.begin()+i);
                cout << "Eliminated: "<< i << endl;
                cout.flush();}
        } 
        first=false;
        m->reset();
        start();
        }
    }
}

Player.cc

#include <iostream>
#include "player.h"
#include "potato.h"
#include "PRNG.h"
using namespace std;

// GLOBAL DECLARATIONS--------------------------------------------------------------------
PRNG randP;

// PLAYER CONSTRUCTOR---------------------------------------------------------------------
Player::Player(unsigned int id, Player::PlayerList &players){
    pid=id;
    Players=players;
    lrpFLAG=false;}

// getId() returns the player's id--------------------------------------------------------
unsigned int Player::getId(){
        return pid;}

// RNPlayer Constructor-------------------------------------------------------------------
RNPlayer::RNPlayer( unsigned int id, Player::PlayerList &players ) : Player(id,players){}

// TOSS FUNCTION--------------------------------------------------------------------------
unsigned int RNPlayer::toss( Potato &potato ){
unsigned int randnum;
if(potato.countdown()){ return getId(); }
    for(;;){    
        randnum=randP(Players.size()-1);
        if (randnum%2==0){
            cout<<"A("<<randnum<<"), ";
            cout.flush();}
        else{
            cout<<"R("<<randnum<<"), ";
            cout.flush();}
        // If our randomly selected player is not the current player...
        if(Players.at(randnum)->getId()!=getId()){
            break;}
    }   
return Players.at(randnum)->toss(potato);
}

// LRPlayer Constructor-------------------------------------------------------------------
LRPlayer::LRPlayer( unsigned int id, Player::PlayerList &players ) : Player(id,players){}

// TOSS FUNCTION
unsigned int LRPlayer::toss( Potato &potato ){
    unsigned int current; // current player
    // Find who our current player is
    for(unsigned int i=0; i<Players.size(); i++){
        if(Players.at(i)->getId()==getId()){
            current=i;
            cout<<"A("<<i<<"), ";}
    }
    // if timer hasn't gone off yet...
    if(potato.countdown()!=true){
    // if this is the FIRST toss, we want to toss left
        if(lrpFLAG==false){
            if(current==0){
                lrpFLAG=true;
                (Players.at(Players.size()-1))->toss(potato);}
            else{
                lrpFLAG=true;
                (Players.at(current-1))->toss(potato);}
            }
        else{
            if(current==Players.size()-1){
                lrpFLAG=false;
                (Players.at(0))->toss(potato);}
            else{
                lrpFLAG=false;
                (Players.at(current+1))->toss(potato);}
            }
        }
    return (Players.at(current))->getId();
}

Main.cc

#include <iostream>
#include <vector>
#include <time.h>
#include "potato.h"
#include "player.h"
#include "umpire.h"
#include "PRNG.h"
using namespace std;

int main(int argc, char *argv[] ){
    int p = 5;
    int tmp;
    unsigned int s;
    PRNG prng1;
    prng1.seed(1234567890);
    // Parse the command line arguments
    switch ( argc ) {
        case 3:
            tmp=atoi(argv[1]);
            s=atoi(argv[2]);
            prng1.seed(s);
            if(tmp<2 || tmp>20){
                cout << "Player must be between 2 and 20 inclusive" << endl;
                    return 0;}
            else{
                p = atoi(argv[1]);}
        }
    // Creating list of players.
    Player::PlayerList players;
    for(int i=0; i<p; i++){
        if(i%2==0){
            players.push_back(new LRPlayer(i,players));}
        else{               
            players.push_back(new RNPlayer(i,players));}
        }

//for (int i=0;i<players.size();i++){
//  cout << "Player at " << i << " id: " << players.at(i)->getId() << endl;}

// How many players?----------------------------------------------------------------------
cout << p << " players in the match" << endl;

// Construct an UMPIRE--------------------------------------------------------------------
Umpire u(players);

// Start the game!------------------------------------------------------------------------
u.start();

}

另请注意:PRNG.h 是一个生成随机数的类。所以 PRNG prng1; int rand=prng1(#) 生成一个介于 0 和 # 之间的随机数。

另外: 当我调用我的折腾函数时,问题就出现了。我没有超出范围,因为当我尝试调用 Players.at(randU)->getID() 时,我根本没有收到任何错误。难道是我无法达到那个玩家的投掷功能吗?我认为这与我指向的东西或记忆有关。我首先在 main.cc 中创建一个 PlayerList 玩家,并在两者之间交替使用 push_back 玩家。但是每个玩家也需要一份名单。也许我遇到了与此有关的错误?

谢谢!非常感谢任何帮助:)

【问题讨论】:

  • 请阅读sscce.org。并且在调试器中运行你的程序,它会帮助你定位哪里异常被抛出,并让你检查变量,看看它为什么会发生。
  • 对于初学者来说,看看异常是什么。不过,几乎可以肯定这是一个超出范围的错误。因此,将向量大小的计算和at() 的参数打印出来,并验证是否在预期范围内。
  • 我如何找出异常是什么?
  • 一般你会使用try { code_throwing_goes_here(); } catch (std::exception const&amp; e) { std::cout &lt;&lt; e.what() &lt;&lt; '\n'; } catch (...) { std::cout &lt;&lt; "unknown exception\n"; }

标签: c++ threadabortexception


【解决方案1】:

抛出的异常必须是 std::out_of_range。您生成的随机数必须大于向量中的元素数。

【讨论】:

    【解决方案2】:

    randU 必须在调用Players.erase() 后重新生成。否则会超出范围。
    或者你应该打破循环:

    for(unsigned int i=0; i<Players.size(); i++){
                if(Players.at(i)->getId()==Players.at(randU)->toss(*f)){
                    Players.erase(Players.begin()+i);
                    cout << "Eliminated: "<< i << endl;
                    cout.flush();
                    break; // BREAK HERE as randU now can be greater than (Players.size() - 1)
                }
            } 
    

    【讨论】:

    • randU 在擦除后确实会重新生成,因为我再次在 start() 上递归。但是,不管怎样,擦除不会为我缩小矢量吗?所以当我打电话给 randU 时,我不会再遇到这个问题了?
    • randUfor(unsigned int i=0; i&lt;Players.size(); i++){ 执行期间不会更改。因此,一旦 Players.erase(Players.begin()+i) 执行完毕,您就有机会使 randU 大于 Players.size()-1
    • 好的,这是个问题,谢谢!但是我仍然遇到调用 toss 本身的问题......
    • 请详细说明toss() 通话问题。如果您可以减少代码大小或将整个源代码作为存档下载,也会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 2014-12-13
    • 2017-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多