回压矢量时出现访问错误

bad access error when pushing back vector

本文关键字:访问 错误      更新时间:2023-10-16

我有两个类:

class card {                //class that represents a card
int cardNumber;         //the ID of the card that give it itse level and suit
std::vector<std::string> suits = { "hearts", "spades", "diamonds", "clubs" };
std::vector<std::string> levels { "Ace", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
std::string suit;
std::string level;
public:

card(int nCardNumber) {     //constructor that initiliazes all properties of the card
    cardNumber = nCardNumber;
    level = levels[cardNumber%13];
    suit = suits[cardNumber/13];
}
void printValue() {         //prints the cards level and suit
    using namespace std;
    cout << level << " of " << suit << endl;
}
};

class hand {            //represents the hand a player is holding
    int playerNumber;
    std::vector<card> playerHand;       //vector of carsa
    public:
    hand(int m_playerNumber) {
        playerNumber = m_playerNumber;
    }  
    void addCard(int cardNumber) {      //adds a card to the hand
      card cardToBeAdded(cardNumber);
    cardToBeAdded.printValue();
    playerHand.push_back(cardToBeAdded);
}
void printHand() {
    using namespace std;
    cout << "Player " << playerNumber << " has:" << endl;
    for (int i = 0; i < 2; i++) {
        playerHand[i].printValue();
    }
}
};

,每当我调用hand中的addCard函数时,我得到EXC_BAD_ACCESS (code=1)。

我已经尝试了一些调试通过声明两个成员在playerHandVector和改变函数重写这些值,而不是追加新的向量,但相同的错误。

任何帮助将不胜感激!

通过适当的调试,很容易看到发生了什么。我已经将您的示例减少到可以重现您的错误的最小值,因为我不相信它与std::vector::push_back有关。

#include <iostream>
#include <vector>
#include <string>
class card {                //class that represents a card
int cardNumber;         //the ID of the card that give it itse level and suit
std::vector<std::string> suits = { "hearts", "spades", "diamonds", "clubs" };
std::vector<std::string> levels { "Ace", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
std::string suit;
std::string level;
public:    
card(int nCardNumber) {     //constructor that initiliazes all properties of the card
    cardNumber = nCardNumber;
    std::cout << cardNumber % 13 << std::endl;
    std::cout << cardNumber / 13 << std::endl;
    level = levels[cardNumber%13];
    suit = suits[cardNumber/13];
}
void printValue() {         //prints the cards level and suit
    using namespace std;
    cout << level << " of " << suit << endl;
}
};
int main() {
    std::vector<card> v;
    for (size_t n = 0; n <= 52; ++n)
    {
        // Replicate "addCard" function
        card c(n);
        c.printValue();
        v.push_back(c);
    }
    return 0;
}

您将在这里注意到两件事:我已经向card构造函数添加了一些调试帮助,因为我认为问题是std::vector<std::string>的访问,并且我正在尝试添加所有52张卡。瞧,前51张卡加成功了;然而,试图添加梅花k有一个错误。让我们看看为什么:

card(int nCardNumber) { // nCardNumber = 52;
    cardNumber = nCardNumber; // 52
    const int nCard = cardNumber % 13; // King
    const int nSuit = cardNumber / 13; // 4
    level = levels[nCard];
    suit = suits[nSuit]; // whoops, out of bounds!
}

你可以在这里看到你正在尝试访问suits[4],这是越界的

您可能有一些代码(您没有显示)使用cardNumber作为数组索引,而不是cardNumber % 13或类似的并且超出数组界限。

如果cardNumber大于等于52,使用cardnumber/13作为数组索引也会失败。

也……

suitslevelscard的非静态成员,因此card的每个实例都有它们的副本。

我不希望每次调用hand::addCard()都会出现问题,但是,如果你的代码创建了很多手牌,给它们添加了很多牌,并且没有清理——那么它会比你预期的更快地耗尽可用内存。

如果你遇到可用内存的限制(这取决于你的操作系统,可用内存等),那么这将解释你的问题

在Visual Studio 2013 Community上编译和运行"正确"。除了VS2013不做成员初始化器列表,所以我必须,把那些打出来。我可能得到错误的唯一方法是让卡片的值超出明显的范围(>52,<0)。这就是你要做的吗?

其他问题:普通卡组没有"1"卡,从关卡向量中删除1。之后,在main中运行以下命令:

for (int i = 0; i < 52; ++i)
    playerHand.addCard(i);

在我的上面,它吐出所有的牌,从A到K,所有4种花色,按顺序。但是,如果我给它的值超出了这些范围它会给出一个错误。

使用vector.at(index)从vector中获取值比使用[]操作符更安全。vector上的[]操作符将其视为原始的c数组,因此如果没有运行某种调试器来捕获它,那么如果为其提供不合适的值,它将是未定义的行为。也就是说,如果你幸运的话,它会毫无原因地崩溃。vector的一个优点是,您可以使用at方法来调用索引,并抛出一个名称非常清楚的异常。

另外,如果您有一个调用用户输入的函数,并且有可能输入错误的数字(就像在这个例子中一样),那么检查输入以确保它是正确的是一个好主意。

正如Peter指出的那样,在类中使用向量只是为了保存标签是不优雅的,并且浪费内存。一个简单的解决方案是使变量:

static std::vector<std::string suits...

static关键字意味着,除了其他你一定要注意的事情之外,它们只会被创建一次,并在类的所有实例中持续存在。