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
函数在删除deck
和table
时出现错误
The output from the terminal
下面是链接的 GitHub 存储库
你这里有问题:
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 不同)。这样我们就可以清楚地知道谁拥有一个对象,因此谁负责删除它们。
您的问题可以通过做几件事轻松解决。
- 不要动态分配数组。
使用 std::vector<>
为您管理分配。
- 不要动态分配生命周期不长于函数的对象。
只需使用局部变量并让范围规则处理它。
- 如果必须动态分配对象,请使用智能指针。
std::unique_ptr 和 std::shared_ptr 很好地管理分配对象的内存。
- 如果您将一个对象传递给另一个对象(并且不传递所有权),则通过引用(而不是指针)传递。
这告诉其他人 class 他们不拥有该对象,因此不应删除它。
一个简单的生活规则是 "Separation of Concerns"。
一个class要么是业务逻辑,要么是资源管理。所以你的 class 要么处理扑克的逻辑,要么处理管理你分配的内存的逻辑(不是两者)。所以任何处理扑克的 class 不应该调用 new/delete 处理 new/delete 的 class 不应该有扑克逻辑。
现在标准库提供了很多资源管理代码,所以你不需要,你可以简单地使用现有代码并专注于你的扑克逻辑。如果在游戏运行后您认为标准资源管理效率不够高,您可以将其作为一项单独的任务进行升级。
我在 运行 我的代码中不断收到此错误。我不确定为什么我一直收到此错误,因为我在使用 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
函数在删除deck
和table
时出现错误
The output from the terminal
下面是链接的 GitHub 存储库
你这里有问题:
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 不同)。这样我们就可以清楚地知道谁拥有一个对象,因此谁负责删除它们。
您的问题可以通过做几件事轻松解决。
- 不要动态分配数组。
使用std::vector<>
为您管理分配。 - 不要动态分配生命周期不长于函数的对象。
只需使用局部变量并让范围规则处理它。 - 如果必须动态分配对象,请使用智能指针。
std::unique_ptr 和 std::shared_ptr 很好地管理分配对象的内存。 - 如果您将一个对象传递给另一个对象(并且不传递所有权),则通过引用(而不是指针)传递。
这告诉其他人 class 他们不拥有该对象,因此不应删除它。
一个简单的生活规则是 "Separation of Concerns"。
一个class要么是业务逻辑,要么是资源管理。所以你的 class 要么处理扑克的逻辑,要么处理管理你分配的内存的逻辑(不是两者)。所以任何处理扑克的 class 不应该调用 new/delete 处理 new/delete 的 class 不应该有扑克逻辑。
现在标准库提供了很多资源管理代码,所以你不需要,你可以简单地使用现有代码并专注于你的扑克逻辑。如果在游戏运行后您认为标准资源管理效率不够高,您可以将其作为一项单独的任务进行升级。