【问题标题】:Terminate called after throwing an instance of 'std::bad_alloc' while using standard vector functions在使用标准向量函数时抛出“std::bad_alloc”实例后调用终止
【发布时间】:2018-11-12 00:30:06
【问题描述】:

我正在处理一项任务,该任务要求我们为真人游戏模拟“淘汰投票”程序。为此,我们使用一个类 (Vote) 来记录要被淘汰的玩家的姓名,另一个 (Voting) 不会在任何地方实例化,因为它的成员是静态的(我们需要它们)。投票存储在 Voting 类中的向量中。

问题是,即使我使用push_back 函数将投票存储在向量中,在运行程序几次后,我得到一个std::length_errorwhat(): basic_string::_M_create。在我关闭它并重新运行后,我第一次收到标题上的错误(std::bad_alloc)。

有什么想法吗?我怀疑它与向量没有正确释放内存有关,但我不确定。

我的代码(Voting.h):

#ifndef VOTING_H_INCLUDED
#define VOTING_H_INCLUDED

#include <vector>
#include <map>
#include "Vote.h" //ignore this one
#include "Team.h" //this one too

class Voting
{
    public:
        static vector <Vote> votes; //votes cast during voting procedure
        static map <string, int> results; //voting results (key: name, value: number of votes)
        static void votingProcess(Team &team); //the whole voting procedure
};

#endif // VOTING_H_INCLUDED

Voting.cpp

#include <vector>
#include <map>
#include <cstdlib>
#include "Vote.h"
#include "Voting.h"

using namespace std;

vector <Vote> Voting::votes(1);  //initialize the vector for the votes

void voteCast(Team &team);

void Voting::votingProcess(Team &team)
{
    voteCast(team);
}


void voteCast(Team &team)
{
    int playerNumber = team.getNumberOfPlayers(); //number of players right now still in the team
    int votingPlayer = 0; //index of the currently voting player
    int votedPlayerIndex = -1; //index of the player to be voted for elimination
    int reasonIndex = -1; //index of the selected reason for voting
    Vote draft;  //temporary empty vote

    srand(time(NULL)); // initialize the RNG
    Voting::votes.clear(); //clear the vector of any past votes

    string reasons[4] = {"Den ta pame kala metaxi mas", "Einai ikanoteros/i apo emena kai ton/ti theoro apeili", "Den exei na prosferei kati stin omada", "Prospathei sinexeia na sampotarei tis prospatheies mas"};
    //some reasons for elimination (i've tried smaller strings and even chars and it didn't work, so don't bother)

    do
    {
        if (team.getPlayers()[votingPlayer].getAge() != 0 && team.getPlayers()[votingPlayer].getVotes() > 0)
        //if the player with index votingPlayer has not been eliminated and has still votes to cast
        {
            do
            {
                votedPlayerIndex = rand() % 11; //select a random player for elimination
                reasonIndex = rand() % 5; //select a random reason for it
            }
            while ((team.getPlayers()[votedPlayerIndex].getAge() == 0) || (votedPlayerIndex == votingPlayer) || (team.getPlayers()[votedPlayerIndex].getImmunity() == true));
            // selection continues if the selected player has already been eliminated,
            //if the selected player is the same as the voting player or if the selected player has immunity from elimination

            team.getPlayers()[votingPlayer].setVotes(team.getPlayers()[votingPlayer].getVotes() - 1); //reduce the player's available votes by 1

            draft.setVotedPlayer(team.getPlayers()[votedPlayerIndex].getName()); //write the name of the player to be voted in an empty Vote object
            draft.setReason(reasons[reasonIndex]); //and the reason too

            Voting::votes.push_back(draft);  //push the Vote obj. in the vector
        }
        else
        {
            votingPlayer++; //ignore and get to the next player
        }
    }
    while (votingPlayer < playerNumber);  //vote casting continues until every player has casted a vote
}

投票.h

#ifndef VOTE_H_INCLUDED
#define VOTE_H_INCLUDED

#include <string>
#include <iostream>

using namespace std;

class Vote
{
    string voted; //name of the player to be eliminated
    string reason; //reason for elimination

    public:
        Vote() { voted = ""; reason = ""; } //constructor without parameters

        Vote(string player, string reason) { voted = player; this -> reason = reason;} //constructor with parameters (this one is used)

        ~Vote() { cout << "Vote object destroyed" << endl; }; //destructor

        string getVotedPlayer() { return voted; } //getters

        string getReason() { return reason; }

        void setVotedPlayer(string player) { voted = player; }  //setters

        void setReason(string reason) { this -> reason = reason; }

        void status() { cout << "Voted player: " << voted << endl << "Reason: " << reason << endl;} //status function
};

#endif // VOTE_H_INCLUDED

【问题讨论】:

  • 你能显示Vote吗,因为这需要复制/移动等,任何问题都会导致std::vector出现问题。
  • 为什么你的班级里的一切都是静态的?假设您有不止一款游戏需要投票。另外,在程序开始时调用 srand() 一次
  • @NeilButterworth 该练习要求我们将所有内容都设为静态。每一次,只有一场比赛在运行。编辑代码以运行 srand() 一次

标签: c++ memory memory-management memory-leaks out-of-memory


【解决方案1】:

原因是您有一个包含 4 个元素的数组(因此只有索引 0..3 有效)并且您允许自己使用 5 个可能的值 (0..4) 对其进行索引,其中 4 不是有效索引。

这里是数组的定义:

字符串原因[4] = {“Den ta pame kala metaxi mas”、“Einai ikanoteros/i apo emena kai ton/ti theoro apeili”、“Den exei na prosferei kati stin omada”、“Prospathei sinexeia na sampotarei tis propatheies mas"};

这里是索引的选择:

reasonIndex = rand() % 5;

这是该索引的用法:

draft.setReason(reasons[reasonIndex]);

这就是为什么您会从 basic_string::_M_create 中看到错误,因为您正在从一个您不知道实际上是字符串的值进行复制。

在设置 reasonIndex 的行中,只需将 5 更改为 4。

【讨论】:

  • 其实我前几天自己解决了,不过还是谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-25
  • 1970-01-01
相关资源
最近更新 更多