我有一段代码正在创建基于图块的级别。
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循环中绘制迭代网格。
尝试访问已删除的变量会不会导致某种崩溃?
答案 0 :(得分:2)
它不会必然导致崩溃。它可能会,它可能不会。它会导致所谓的未定义行为:
未定义的行为
本国际标准没有要求的行为
它可能像破坏宇宙一样崩溃。
答案 1 :(得分:2)
可能导致崩溃。这取决于该内存是否被另一个对象覆盖和/或内存系统将该页面重新分配给另一个进程(或从当前进程中释放该页面)。最重要的是你不能依赖它(正如你所知)
答案 2 :(得分:1)
删除后访问对象是未定义的行为。未定义的行为可能意味着任何事情,从“看似成功”到“崩溃”再到“格式化硬盘”。
答案 3 :(得分:1)
您所做的事情被称为“未定义的行为”。
未定义的行为并不意味着“会崩溃”,这意味着任何事情都可能发生。该程序可以格式化你的硬盘,它可以播放一个巴赫奏鸣曲,它可以在屏幕上绘制一个daffy duck的图片,它可以给你一个负值,并且在每种情况下它都会完全你要的是什么。
不包括崩溃,崩溃也是如此。
现在让我们假设一个合理的C ++实现。方法Level::Draw
与您传递的Level
实例无关,因此您调用的函数不依赖于实例。该实例作为参数传递给此函数,作为指向堆中某些内存的指针,该内存曾经是变量的副本。从那时起,它已被回收用于其他目的,或者可能包含有关堆的簿记信息 - 有什么是未定义的。 (并且,如果运行时将页面返回到系统,则访问它可能会出现段错误)
然后,您将该垃圾解释为某些值。事情非常好,因为随机垃圾看起来像C ++ int
eger(在这种情况下,作为负整数),几乎总是在大多数系统上。
现在,一旦你开始取消引用指针(并因此访问“随机”部分内存)或写入this
状态,可能会发生崩溃(如果不是,那么稍后,或者其它地方)。