我试着在几个编译器上运行代码,得到了不同的结果。我要么得到了一些奇怪的退出代码,比如-1073741819 (0xC0000005)
或free(): double free detected in tcache 2
,要么在调试时得到了SIGTRAP (Trace/breakpoint trap) SIGSEGV (Segmentation fault)
。
我99%确定问题是我释放了两次ships数组。但是为什么当我没有在两个玩家上运行func()两次或者我修改了代码中的其他内容时,我没有得到错误?问题到底是什么?我如何修复错误?
是的我使用动态数组而不是向量,因为我正在尝试练习和学习。是的我知道这种内存分配方法会产生内存碎片,但我从不更改矩阵的大小,所以这应该不是问题。
代码:
struct point_t {
int x;
int y;
point_t();
};
point_t::point_t() {
this->x = 0;
this->y = 0;
}
struct ship_t {
int size;
point_t end_coords[2];
};
struct player_t {
int **map;
int map_size;
ship_t *ships;
int ships_count;
player_t(int, ship_t *, int);
~player_t();
};
player_t::player_t(int map_size, ship_t *ships, int ships_count) {
this->map = nullptr;
this->map_size = map_size;
this->ships = ships;
this->ships_count = ships_count;
}
player_t::~player_t() {
// Free map memory
// Free each column (sub-array)
for(int i = 0; i < map_size; i++) {
delete[] map[i];
}
// Free each row (array of pointers)
delete[] map;
map = nullptr;
map_size = 0;
delete[] ships;
ships = nullptr;
ships_count = 0;
}
void func(player_t &player) {
player.map = new int *[player.map_size];
for(int i = 0; i < player.map_size; i++) {
player.map[i] = new int[player.map_size];
for(int j = 0; j < player.map_size; j++) {
player.map[i][j] = 0;
}
}
}
int main()
{
ship_t *ships = new ship_t[(5 * 5) / 2];
for(int i = 0; i < 5; i++) {
ships[i].size = i + 1;
}
player_t player1 = player_t(5, ships, 5);
player_t player2 = player_t(5, ships, 5);
func(player1);
func(player2);
return 0;
}
字符串
1条答案
按热度按时间mtb9vblg1#
用Visual Studio运行你的代码给了我:
字符串
在做
delete[] ships;
的时候。第一个问题是你试图在ships构造函数中初始化点,但是:
型
这条语句将一个默认的初始化点赋给ships的
end_coords
成员中的第三个点。2不幸的是,数组有两个点大。此外,由于
player_t
析构函数会销毁船只,所以你将船只的所有权交给了player_t
。但是你将同一个动态分配数组的所有权交给了两个玩家:型
不是一个好主意。同样的船阵被两个玩家使用,这没有意义,因为每个玩家都应该有自己的船,我想。
最后,你不应该调用player的析构函数,因为它会在返回(作用域退出)时再次被调用。
最小修改固定代码:
在
ship_t
构造函数中注解掉这一行:型
分配两艘船阵,给予每个玩家所有权:
型
更C++风格的解决方案
让我们用它们的名字来调用结构体。然后在结构体中使用默认的初始化来避免无用的构造函数。删除所有的分配,除非真的真的需要。让我们使用
std::vector<>
。我不喜欢矢量的矢量用于Map,但在这种情况下,它确实是一个简单的解决方案。使用矢量时不需要存储大小。最后,使用move将ship矢量复制到每个播放器中,以防有什么临时的东西传来传去型
更C++风格的版本,带内存分配:
这里我没有使用
std::vector
(但这不是一个好主意)。注意我们如何将一个vector int初始化为0,并且你不需要一个指向指针的指针。通过几个操作符,管理Map会容易得多。作为一个例子,我正在打印你的Map。建议:不要使用i
和j
。行和列使用r
和c
,以避免意外交换它们的含义。型