malloc: *** 对象错误:未分配正在释放的指针

malloc: *** error for object: pointer being freed was not allocated

我在 运行 我的代码中不断收到此错误。我不确定为什么我一直收到此错误,因为我在使用 new 运算符分配的两个对象上调用 delete

我在 Xcode 中尝试了 运行 并得到 thread 1: signal SIGABRT error.

PokerV2.cpp

int main() {    
    bool game_flag = true;

    Poker_Game game1;

    game1.initialise_game();

    game1.game_run();

    while (game_flag) { 
        char input = 'a';
        game_flag = false;
        game1.game_run(game1.get_current_players());
        std::cout << "Press 'y' to continue";
        std::cin >> input;
        if (input == 'y') {
            game_flag = true;
        }
    }
}

poker_game_class.hpp

void Poker_Game::game_run() {
    int lowest = 10;
    int num = 0;
    // Create the deck and table dynamically
    Deck *deck = new Deck();
    Table *table = new Table(_player_num);

    deck->deal_cards(table->get_all_players(), _player_num, *table);

    for (int i = 0; i < 4; i++) {
        table->set_game_flag(i);
        table->set_highest_bet(0);

        for (int z = 0; z < table->get_player_num(); z++) {
            table->players_turn(z);
        }
    }

    for (int i = 0; i < table->get_player_num(); i++) {
        if (table->get_player(i).calculate_score(*table) < lowest) {
            num = i;
        }
    }

    std::cout << "The winner is player: " << num << "\n";
    std::cout << "The winner has won: £" << table->get_pot() << "\n";

    //Add total pot to players cash

    float current_balance = table->get_player(num).get_balance();
    float balance_after_win = current_balance + table->get_pot();

    table->get_player(num).set_balance(balance_after_win);

    std::cout << "Winners balance: £" << table->get_player(num).get_balance();

    this->Current_players = table->get_all_players();

    delete deck;
    delete table;
}

game_run函数在删除decktable时出现错误

The output from the terminal

下面是链接的 GitHub 存储库

https://github.com/mbh1620/PokerV2/tree/master/PokerV2

你这里有问题:

Player * Table::get_all_players()
{
    return Players;
}

Poker_Game 调用此函数时,您将返回一个指针(和所有权):

    // One place you call it from.
    set_current_players(table -> get_all_players());

问题是两个对象现在都在声明 Players 的所有权,并且都在它们拥有的指针上调用 delete []

Poker_Game::~Poker_Game()
{
    delete[] Current_players;
}
Table::~Table()
{
    delete[] Players;
}

没有说这是你唯一的错误。

您基本上已经落入应用程序中糟糕的所有权语义的陷阱。在 C++ 中,我们通过使用特定类型和语言构造来显式标记所有权来解决此问题(与 C 不同)。这样我们就可以清楚地知道谁拥有一个对象,因此谁负责删除它们。

您的问题可以通过做几件事轻松解决。

  1. 不要动态分配数组。
    使用 std::vector<> 为您管理分配。
  2. 不要动态分配生命周期不长于函数的对象。
    只需使用局部变量并让范围规则处理它。
  3. 如果必须动态分配对象,请使用智能指针。
    std::unique_ptr 和 std::shared_ptr 很好地管理分配对象的内存。
  4. 如果您将一个对象传递给另一个对象(并且不传递所有权),则通过引用(而不是指针)传递。
    这告诉其他人 class 他们不拥有该对象,因此不应删除它。

一个简单的生活规则是 "Separation of Concerns"。

一个class要么是业务逻辑,要么是资源管理。所以你的 class 要么处理扑克的逻辑,要么处理管理你分配的内存的逻辑(不是两者)。所以任何处理扑克的 class 不应该调用 new/delete 处理 new/delete 的 class 不应该有扑克逻辑。

现在标准库提供了很多资源管理代码,所以你不需要,你可以简单地使用现有代码并专注于你的扑克逻辑。如果在游戏运行后您认为标准资源管理效率不够高,您可以将其作为一项单独的任务进行升级。