Deleting pointers in destructor
我在类的构造函数中分配了一些指针,然后尝试在其析构函数中删除它们:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | TileMap::TileMap(int x, int y) { mapSize.x = x; mapSize.y = y; p_p_map = new Tile*[x]; for(int i = 0; i < x; i++) { p_p_map[i] = new Tile[y]; } randomize(); } TileMap::~TileMap() { for(int i = 0; i < mapSize.x; i++) { delete p_p_map[i]; } delete p_p_map; } void TileMap::randomize() { for(int i = 0; i < mapSize.x; i++) { for(int j = 0; j < mapSize.y; j++) { p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType()); } } } |
在程序结束时,调用析构函数以释放我分配的指针的内存,但是当到达"删除p_p_map [i];"时,该析构函数将被释放。 在析构函数中,XCode通知我未分配指针。 我是C ++的新手,但我觉得我已经为randomize()函数中的指针显式分配了内存。
我犯什么错误?
What error am I making?
一些:
首先,正如@uesp所指出的,您不匹配新呼叫并删除呼叫
其次,您正在使用"内存泄漏运算符":
1 | p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType()); |
构造
由于指针未存储在任何地方,因此会泄漏。
第三,您不尊重RAII。尽管从技术上来讲这并不是错误,但是编写代码的方式并不安全,并且在内存不足的情况下,您将得到UB。
例如,如果构造一个具有x和y较大值的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | TileMap::TileMap(int x, int y) { // e.g. (x = 1024 * 1024, y = 1024 * 1024 * 1024) mapSize.x = x; mapSize.y = y; p_p_map = new Tile*[x]; // allocate 1049600 pointers block for(int i = 0; i < x; i++) { p_p_map[i] = new Tile[y]; // run out of memory (for example) half way through the loop } randomize(); } |
根据分配失败的地方,构造函数将无法完成执行,这意味着
在这种情况下,所有分配给类的类都会泄漏,并且(特别是如果分配了大容量的话)您的应用程序将处于低内存状态。
要解决此问题,请确保每个指针都由类的不同实例(RAII的一部分)管理。这样可以确保如果分配失败,则在退出范围之前释放已分配的资源,这是堆栈展开的一部分(如@CaptainObvlious所说,对数组使用std :: vector,对每个元素使用std :: unique_ptr)。
您必须将
1 | p_p_map = new Tile*[x]; |
您必须像这样删除它:
1 | delete[] p_p_map; |
和相同
1 | delete[] p_p_map[i]; |
如果您创建类似:
1 | pSomething = new Type; |
然后您将其删除:
1 | delete pSomething; |