int main() {
Employee *e = new Employee();
delete e;
delete e;
...
delete e;
return 0;
}
8 回答
如果您多次尝试通过指针访问对象,则会得到未定义的行为。delete
这意味着几乎任何事情都可能发生,从“看起来工作”到“崩溃”或完全随机的事情。
这是未定义的行为,所以任何事情都可能发生。
可能发生的事情很糟糕。通常,免费存储是一个精心管理的免费和已分配块系统,new
并delete
进行簿记以使所有内容保持一致状态。如果你delete
再看一遍,系统很可能对无效数据做同样的记账,突然空闲存储处于不一致的状态。这被称为“堆损坏”。
一旦发生这种情况,您所做的任何事情new
或delete
可能会产生不可预知的结果,其中可能包括尝试在应用程序的内存区域之外写入、默默地破坏数据、错误地认为没有更多的内存,或者双重或重叠分配。如果幸运的话,程序很快就会崩溃,尽管你仍然无法弄清楚原因。如果你不走运,它会继续运行,结果很糟糕。
除了关于“未定义行为”的旧观点,这意味着任何事情都可能发生,从无到有通往主内存中打开的地狱第七圈的网关,实际上,在大多数实现中通常会发生的是程序将继续运行过去删除,然后在稍后的某个不相关的内存分配中神秘地崩溃。
您可能正在冒险进入“未定义行为”领域。
在许多系统上,这会导致崩溃;例如,在我的 Linux 机器上:
*** glibc detected *** ./cctest: double free or corruption (fasttop): 0x0000000000d59900 ***
======= Backtrace: =========
/lib/libc.so.6[0x7f399f4cbdd6]
/lib/libc.so.6(cfree+0x6c)[0x7f399f4d074c]
./cctest[0x400a7a]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f399f474abd]
./cctest[0x400959]
如果你真的很幸运,它会崩溃。通常情况下,它会存储业力,直到您的 CEO 向您最重要的新客户展示代码,此时它将破坏/破坏他们的所有数据。
在检查或调试版本中,这种事情经常被捕获,但它可能完全未被发现并在以后造成严重破坏。当涉及多个线程时,这一点尤其深刻。
如果您担心这可能会在您的应用程序中发生,请完全停止使用原始指针,这样您就不需要删除(例如切换到),或者在删除它们后shared_ptr
始终将指针设置为NULL
(或 0,或者更好)。nullptr
对空指针调用 delete 保证什么都不做。
这不安全,并且不确定实际发生的情况:
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.2
即使有时我们可以在删除 ptr 后访问内存位置。我们不应该再次删除相同的指针或为该指针赋值(导致不一致的行为)。
但是我们可以使用相同的指针变量来指向不同的内存地址(有效内存)
int *p = new int(10);
std::cout << "in main" << std::endl;
std::cout <<*p << std::endl;
std::cout << p << std::endl;
std::cout << &p<< std::endl;
delete p;
std::cout << "in main2 after delete" << std::endl;
std::cout <<*p << std::endl;
std::cout << p << std::endl;
std::cout << &p<< std::endl;
p = new int(100);
std::cout << "in main3" << std::endl;
std::cout <<*p << std::endl;
std::cout << p << std::endl;
std::cout << &p<< std::endl;
导致输出
in main
10
0x558b597a8eb0
0x7fff8f7a5ba0
in main2 after delete
0
0x558b597a8eb0
0x7fff8f7a5ba0
in main3
100
0x558b597a8eb0
0x7fff8f7a5ba0