提问人:Ash 提问时间:12/19/2009 最后编辑:TrebledJAsh 更新时间:6/1/2020 访问量:18984
C++ 删除 - 它删除了我的对象,但我仍然可以访问数据?
C++ delete - It deletes my objects but I can still access the data?
问:
我编写了一个简单的、有效的俄罗斯方块游戏,每个方块都作为类 singleblock 的实例。
class SingleBlock
{
public:
SingleBlock(int, int);
~SingleBlock();
int x;
int y;
SingleBlock *next;
};
class MultiBlock
{
public:
MultiBlock(int, int);
SingleBlock *c, *d, *e, *f;
};
SingleBlock::SingleBlock(int a, int b)
{
x = a;
y = b;
}
SingleBlock::~SingleBlock()
{
x = 222;
}
MultiBlock::MultiBlock(int a, int b)
{
c = new SingleBlock (a,b);
d = c->next = new SingleBlock (a+10,b);
e = d->next = new SingleBlock (a+20,b);
f = e->next = new SingleBlock (a+30,b);
}
我有一个函数,可以扫描一整行,并遍历块的链接列表,删除相关指针并重新分配 ->next 指针。
SingleBlock *deleteBlock;
SingleBlock *tempBlock;
tempBlock = deleteBlock->next;
delete deleteBlock;
游戏运行正常,方块被正确删除,一切都按预期运行。但是,在检查时,我仍然可以访问已删除数据的随机位。
如果我在删除后打印每个已删除的单块“x”值,其中一些返回随机垃圾(确认删除),其中一些返回 222,告诉我即使调用析构函数,数据实际上也没有从堆中删除。许多相同的试验表明,始终是相同的特定块未被正确删除。
结果:
Existing Blocks:
Block: 00E927A8
Block: 00E94290
Block: 00E942B0
Block: 00E942D0
Block: 00E942F0
Block: 00E94500
Block: 00E94520
Block: 00E94540
Block: 00E94560
Block: 00E945B0
Block: 00E945D0
Block: 00E945F0
Block: 00E94610
Block: 00E94660
Block: 00E94680
Block: 00E946A0
Deleting Blocks:
Deleting ... 00E942B0, X = 15288000
Deleting ... 00E942D0, X = 15286960
Deleting ... 00E94520, X = 15286992
Deleting ... 00E94540, X = 15270296
Deleting ... 00E94560, X = 222
Deleting ... 00E945D0, X = 15270296
Deleting ... 00E945F0, X = 222
Deleting ... 00E94610, X = 222
Deleting ... 00E94660, X = 15270296
Deleting ... 00E94680, X = 222
能够从坟墓之外访问数据是否值得期待?
对不起,如果这有点啰嗦。
答:
它还不会将内存归零/更改......但在某些时候,地毯会从你的脚下被拉出来。
不,这当然是不可预测的:这取决于内存分配/释放的速度。
评论
delete
能够从坟墓之外访问数据是否值得期待?
在大多数情况下,是的。调用 delete 不会将内存归零。
请注意,未定义行为。使用某些编译器时,内存可能会归零。调用 delete 时,会发生内存被标记为可用,因此下次有人执行新操作时,可能会使用内存。
如果你仔细想想,这是合乎逻辑的——当你告诉编译器你不再对内存感兴趣(使用 delete)时,计算机为什么要花时间将其归零。
评论
new
malloc
delete 会解除分配内存,但不会对其进行修改或将其清零。不过,您不应该访问已释放的内存。
评论
能够从坟墓之外访问数据是否值得期待?
这在技术上称为未定义行为。如果它为您提供一罐啤酒,也不要感到惊讶。
评论
memset
这就是 C++ 所说的未定义行为 - 您也许能够访问数据,也可能无法访问。无论如何,这是错误的做法。
当您通过 释放内存时,系统不会清除内存。因此,在分配内存以供重用和覆盖之前,仍然可以访问这些内容。delete()
评论
删除对象后,没有定义它占用的内存内容会发生什么。这确实意味着该内存可以自由重用,但实现不必覆盖最初存在的数据,也不必立即重用内存。
你不应该在对象消失后访问内存,但不应该推测某些数据仍然在那里。
是的,有时可以预料到。虽然为数据保留了空间,但只是使使用 创建的指针失效,允许在先前保留的位置写入数据;它不一定会删除数据。但是,您不应依赖该行为,因为这些位置的数据可能随时更改,这可能会导致程序行为异常。这就是为什么在指针上使用(或分配了 的数组)后,应为其分配 NULL,以便无法篡改无效指针,假设您不会使用或再次使用该指针之前分配内存。new
delete
new
delete
delete[]
new[]
new
new[]
评论
delete
删除不会删除任何内容 - 它只是将内存标记为“可自由重用”。在一些其他分配调用保留并填充该空间之前,它将拥有旧数据。然而,依赖它是一个很大的禁忌,基本上如果你删除了一些东西,就忘记它。
在这方面,库中经常遇到的一种做法是 Delete 函数:
template< class T > void Delete( T*& pointer )
{
delete pointer;
pointer = NULL;
}
这可以防止我们意外访问无效的内存。
请注意,调用 是完全可以的。delete NULL;
评论
char *ptr = new char; char *ptr2 = ptr; Delete(ptr); *ptr2 = 0;
它将导致未定义的行为并删除释放内存,它不会用零重新初始化它。
如果你想让它归零,那就做:
SingleBlock::~SingleBlock()
{ x = y = 0 ; }
评论
堆内存就像一堆黑板。想象一下,你是一名老师。当你在课堂上教书时,黑板是属于你的,你可以用它做任何你想做的事情。您可以在上面涂鸦并根据需要覆盖内容。
當課程結束,你將要離開教室時,沒有政策要求你擦掉黑板 - 你只需將黑板交給下一位老師,他通常可以看到你寫下的文章。
评论
尽管运行时可能不会报告此错误,但使用适当的错误检查运行时(如 Valgrind)会在释放内存后提醒您内存的使用情况。
我建议,如果您使用 / 和原始指针(而不是类似指针)编写代码,请在 Valgrind 下进行单元测试,至少有机会发现此类错误。new
delete
std::make_shared()
好吧,我也一直在思考这个问题,我试图运行一些测试来更好地了解引擎盖下发生的事情。标准答案是,在调用 delete 之后,您不应该期望访问该内存点有任何好处。 然而,这在我看来还不够。调用 delete(ptr) 时到底发生了什么?这是我发现的。我在 Ubuntu 16.04 上使用 g++,所以这可能在结果中起作用。
在使用 delete 运算符时,我首先期望的是释放的内存将交还给系统以供其他进程使用。让我说,在我尝试过的任何情况下,这都不会发生。
使用 delete 释放的内存似乎仍然分配给它首先使用 new 分配给它的程序。我已经试过了,调用 delete 后内存使用量没有减少。我有一个软件,它通过新调用分配了大约 30MB 的列表,然后在随后的删除调用中释放它们。发生的事情是,在程序运行时查看系统监视器,即使在删除调用后长时间睡眠,我的程序的内存消耗也是相同的。没有减少!这意味着删除不会将内存释放到系统。
事实上,看起来程序分配的内存是他的永远!但是,关键是,如果解除分配,内存可以由同一程序再次使用,而不必再分配任何内存。我试图分配 15MB,释放它们,然后再分配 15MB 的数据,但程序从未使用 30MB。系统监视器总是显示它大约 15MB。关于之前的测试,我所做的只是改变事情发生的顺序:一半分配,一半解除分配,另一半分配。
因此,显然程序使用的内存可以增加,但永远不会减少。我认为,在危急情况下,例如当没有更多可用内存时,也许真的会为其他进程释放内存。毕竟,当其他进程要求它时,让程序永远保留自己的内存有什么意义呢?因此,我再次分配了 30MB,在解除分配它们的同时,我尽可能多地运行物理内存。我希望看到我的软件将其内存分发给 memtester。但你猜,它没有发生!memtester
我编了一个简短的截屏视频,展示了这个东西的实际效果:
老实说,有一种情况发生了一些事情。当我在程序的释放过程中尝试使用超过可用物理内存的 memtester 时,我的程序使用的内存下降到大约 3MB。然而,memtester进程被自动杀死了,发生的事情更令人惊讶!每次删除调用时,我的程序的内存使用量都会增加!就好像 Ubuntu 在 memtester 事件后恢复了所有内存一样。
取自 http://www.thecrowned.org/c-delete-operator-really-frees-memory
上一个:我应该如何将对象传递给函数?
下一个:指向类数据成员“::*”的指针
评论
delete
forget