删除析构函数中的指针

时间:2014-11-03 14:34:31

标签: c++ xcode macos pointers

我有一些指针,我在类的构造函数中分配,然后尝试在其析构函数中删除:

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());

        }

    }

}

在程序结束时,调用析构函数来释放我分配的指针的内存,但是当它到达&#34;删除p_p_map [i];&#34;在析构函数中,XCode通知我指针未分配。我是C ++的新手,但我觉得我非常明确地为randomize()函数中的指针分配了内存。

我犯了什么错误?

2 个答案:

答案 0 :(得分:1)

您必须将deletenewdelete[]new[]匹配。将一个与另一个混合会导致问题。所以如果你这样做:

p_p_map = new Tile*[x];

你必须删除它:

delete[] p_p_map;

相同
delete[] p_p_map[i];

如果您创建类似:

pSomething = new Type;

然后你删除它:

delete pSomething;

答案 1 :(得分:1)

  

我犯了什么错误?

一些:

首先,正如@uesp指出的那样,你不匹配新的和删除调用

其次,您正在使用&#34;内存泄漏运算符&#34;:

p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());

构造new Tile(...)分配内存。然后,取消引用该存储器(未存储在任何地方),并将结果分配给p_p_map [i] [j]。

因为指针没有存储在任何地方,所以它被泄露了。

第三,你不尊重RAII。虽然这在技术上本身并不是一个错误,但是编写代码的方式是不安全的,而在内存不足的情况下,你会获得UB。

例如,如果构建一个x和y值较大的Tile实例会发生什么:

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();
}

根据您的分配失败的地方,您的构造函数将无法完成执行,这意味着您的TileMap实例是&#34;半结构&#34; (即处于无效状态)并且不会调用析构函数。

在这种情况下,所分配的类的所有内容都会泄露,并且(特别是如果你分配了一个大的)你的应用程序将处于低内存条件下。

要解决此问题,请确保每个指针都由一个不同的类实例(RAII的一部分)管理。这确保了如果分配失败,则在退出作用域之前释放分配的资源,作为堆栈展开的一部分(如@CaptainObvlious所说,对数组使用std :: vector,对每个元素使用std :: unique_ptr)。