int main() {
Employee *e = new Employee();
delete e;
delete e;
...
delete e;
return 0;
}
int main() {
Employee *e = new Employee();
delete e;
delete e;
...
delete e;
return 0;
}
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]
shared_ptr
),要么在删除后始终将指针设置为NULL
(或0,或更好的是nullptr
)。 在空指针上调用delete保证什么也不会发生。这样做是不安全的,而且可能发生的情况是未定义的:
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.2
尽管有时我们可以在删除指针后访问内存位置,但我们不应再次删除同一指针或将值分配给该指针(会导致不一致的行为)。
但是,我们可以使用相同的指针变量来指向不同的内存地址(有效内存)。
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