为什么访问已删除的对象不会使我的程序崩溃? [重复]

问题描述 投票:0回答:4

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

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

为了咯咯笑,我决定删除关卡实例。这样做之后,我发现我仍然可以调用它的 Draw 方法。

在调试器中,TilesWide 和 TilesTall 的值是一个巨大的负数,因此在我的 for 循环迭代网格中没有任何内容。

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

c++ memory-management
4个回答
2
投票

它不会必然导致崩溃。它可能会,也可能不会。它会导致所谓的undefined behavior

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

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


2
投票

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


1
投票

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

而未定义的行为并不意味着“会崩溃”,它意味着任何事情都有可能发生。该程序可以格式化您的硬盘驱动器,可以播放巴赫奏鸣曲,可以在屏幕上画达菲鸭的图片,可以给您一个负值,并且在任何情况下它都会exactly您所要求的。

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

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

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

然后你继续将垃圾解释为一些值。一切都很好,因为随机垃圾在大多数系统上几乎总是看起来像 C++

int
eger(在本例中为负整数)。

现在,一旦你开始取消引用指针(因此,访问内存的“随机”部分),或写入

this
的状态,崩溃很可能发生(如果不是那么,那么稍后,或其他地方)。


1
投票

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

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.