C++ 为什么不是';访问已删除的对象会使我的程序崩溃吗?

C++ 为什么不是';访问已删除的对象会使我的程序崩溃吗?,c++,memory-management,C++,Memory Management,我有一段代码正在创建一个基于平铺的级别 class Level { //Variables //=================================================== public: Tile *** TileGrid; //A 2d array of pointers to tiles int TilesWide, TilesTall; //Methods //========================================

我有一段代码正在创建一个基于平铺的级别

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::~Level(){
for(int i=0;i
对于傻笑,我决定删除我的Level实例。在我这样做之后,我发现我仍然可以调用它的Draw方法

在调试器中,tileswead和TilesTall的值都是一个巨大的负数,因此在我的循环中没有任何东西会对网格进行迭代

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

它不一定会导致崩溃。可能行,也可能不行。它会导致所谓的未定义行为:

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

它可能会像摧毁宇宙一样崩溃。

它不一定会导致崩溃。可能行,也可能不行。它会导致所谓的未定义行为:

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


它可能会像摧毁宇宙一样崩溃。

它可能会导致崩溃。这取决于该内存是否被另一个对象覆盖和/或内存系统是否将该页重新分配给另一个进程(或从当前进程中取消分配该页)。底线是你不能依赖它工作(正如你已经知道的)

它可能会导致崩溃。这取决于该内存是否被另一个对象覆盖和/或内存系统是否将该页重新分配给另一个进程(或从当前进程中取消分配该页)。底线是您不能依赖它工作(正如您已经知道的)

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

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

您所做的就是所谓的“未定义的行为”

未定义的行为并不意味着“会崩溃”,它意味着任何事情都可能发生。这个程序可以格式化你的硬盘,它可以播放巴赫奏鸣曲,它可以在屏幕上画一幅达菲鸭的画,它可以给你一个负值,在任何情况下,它都会是你想要的

不崩溃也包括在内,就像崩溃一样

现在让我们假设一个合理的C++实现。方法

Level::Draw
不随传递它的
Level
的实例而变化,因此调用的函数不依赖于实例。实例作为参数传递给该函数,作为指向堆中某个内存的指针,该内存过去是变量的副本。从那时起,它就被回收用于其他目的,或者可能包含关于堆的簿记信息——还有什么是未定义的。(而且,如果运行时将页面返回给系统,访问它可能会出错)

然后继续将垃圾解释为一些值。一切都很好,因为随机的垃圾看起来像一个C++代码> int /代码> EGER(在这种情况下,作为一个负整数)在大多数系统上总是如此。
现在,一旦您开始取消引用指针(以及访问内存中的“随机”部分),或写入到
的状态,很可能会发生崩溃(如果不是,那么以后,或者其他地方)。

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

未定义的行为并不意味着“会崩溃”,它意味着任何事情都可能发生。这个程序可以格式化你的硬盘,它可以播放巴赫奏鸣曲,它可以在屏幕上画一幅达菲鸭的画,它可以给你一个负值,在任何情况下,它都会是你想要的

不崩溃也包括在内,就像崩溃一样

现在让我们假设一个合理的C++实现。方法

Level::Draw
不随传递它的
Level
的实例而变化,因此调用的函数不依赖于实例。实例作为参数传递给该函数,作为指向堆中某个内存的指针,该内存过去是变量的副本。从那时起,它就被回收用于其他目的,或者可能包含关于堆的簿记信息——还有什么是未定义的。(而且,如果运行时将页面返回给系统,访问它可能会出错)

然后继续将垃圾解释为一些值。一切都很好,因为随机的垃圾看起来像一个C++代码> int /代码> EGER(在这种情况下,作为一个负整数)在大多数系统上总是如此。
现在,一旦您开始取消引用指针(以及访问内存的“随机”部分),或写入到
这个
的状态,很可能会发生崩溃(如果不是这样,那么以后,或者其他地方)。

这个答案假设存在标准不知道的“进程”和“页面”。(在实际系统中,对象本身不太可能有整个页面)是的。我没有考虑标准,但实际上从操作系统和CPU的角度来看会发生什么。我并不是说该对象本身有一个页面,但是如果该页面(取决于操作系统)没有被进程使用,则可能会返回该页面。这个答案假设存在标准不知道的“进程”和“页面”。(在实际系统中,对象本身不太可能有整个页面)是的。我没有考虑过