为什么不访问已删除的对象导致我的程序崩溃?

时间:2013-02-13 20:16:34

标签: c++ memory-management

我有一段代码正在创建基于图块的级别。

class Level {

//Variables
//===================================================
public:
    Tile *** TileGrid;  //A 2d array of pointers to tiles
    int TilesWide, TilesTall;

//Methods
//===================================================
public:
    Level::Level(char * fileName);
    Level::~Level();
    void Draw();
};

我为TileGrid分配内存,一切都很好。我也为课程设置了析构函数。

Level::~Level() {

    for (int i = 0; i < TilesTall; i++) {
        for (int j = 0; j < TilesWide; j++)
            //delete the looped tile being pointed to
            delete TileGrid[i][j];

        //delete the row
        delete [] TileGrid[i];
    }

    //delete the array of rows
    delete [] TileGrid;
}

对于咯咯笑声,我决定删除我的Level实例。在我这样做之后,我发现我仍然可以调用它的Draw方法。

在调试器中,TilesWide和TilesTall的值是一个巨大的负数,所以没有任何东西在我的for循环中绘制迭代网格。

尝试访问已删除的变量会不会导致某种崩溃?

4 个答案:

答案 0 :(得分:2)

它不会必然导致崩溃。它可能会,它可能不会。它会导致所谓的未定义行为

  

未定义的行为
  本国际标准没有要求的行为

它可能像破坏宇宙一样崩溃。

答案 1 :(得分:2)

可能导致崩溃。这取决于该内存是否被另一个对象覆盖和/或内存系统将该页面重新分配给另一个进程(或从当前进程中释放该页面)。最重要的是你不能依赖它(正如你所知)

答案 2 :(得分:1)

删除后访问对象是未定义的行为。未定义的行为可能意味着任何事情,从“看似成功”到“崩溃”再到“格式化硬盘”。

答案 3 :(得分:1)

您所做的事情被称为“未定义的行为”。

未定义的行为并不意味着“会崩溃”,这意味着任何事情都可能发生。该程序可以格式化你的硬盘,它可以播放一个巴赫奏鸣曲,它可以在屏幕上绘制一个daffy duck的图片,它可以给你一个负值,并且在每种情况下它都会完全你要的是什么。

不包括崩溃,崩溃也是如此。

现在让我们假设一个合理的C ++实现。方法Level::Draw与您传递的Level实例无关,因此您调用的函数不依赖于实例。该实例作为参数传递给此函数,作为指向堆中某些内存的指针,该内存曾经是变量的副本。从那时起,它已被回收用于其他目的,或者可能包含有关堆的簿记信息 - 有什么是未定义的。 (并且,如果运行时将页面返回到系统,则访问它可能会出现段错误)

然后,您将该垃圾解释为某些值。事情非常好,因为随机垃圾看起来像C ++ int eger(在这种情况下,作为负整数),几乎总是在大多数系统上。

现在,一旦你开始取消引用指针(并因此访问“随机”部分内存)或写入this状态,可能会发生崩溃(如果不是,那么稍后,或者其它地方)。