忽略编程风格和设计,在堆栈上分配的变量上调用delete是"安全的"吗?
例如:
int nAmount; delete &nAmount;
要么
class sample { public: sample(); ~sample() { delete &nAmount;} int nAmount; }
Mr Fooz.. 102
不,调用delete
堆栈分配的变量是不安全的.你应该只调用delete
创建的东西new
.
对于每个malloc
或者calloc
,应该只有一个free
.
每个new
应该只有一个delete
.
每个new[]
应该只有一个delete[]
.
对于每个堆栈分配,应该没有明确的释放或删除.在适用的情况下,会自动调用析构函数.
在一般情况下,你不能随意搭配任何这些,例如没有free
-ing或delete[]
-ing一个new
对象.这样做会导致未定义的行为.
不,调用delete
堆栈分配的变量是不安全的.你应该只调用delete
创建的东西new
.
对于每个malloc
或者calloc
,应该只有一个free
.
每个new
应该只有一个delete
.
每个new[]
应该只有一个delete[]
.
对于每个堆栈分配,应该没有明确的释放或删除.在适用的情况下,会自动调用析构函数.
在一般情况下,你不能随意搭配任何这些,例如没有free
-ing或delete[]
-ing一个new
对象.这样做会导致未定义的行为.
好吧,我们来试试吧:
jeremy@jeremy-desktop:~$ echo 'main() { int a; delete &a; }' > test.cpp jeremy@jeremy-desktop:~$ g++ -o test test.cpp jeremy@jeremy-desktop:~$ ./test Segmentation fault
显然它根本不安全.
请记住,当您使用new(或malloc)分配内存块时,分配的实际内存块将大于您的要求.内存块还将包含一些簿记信息,以便在释放块时,可以轻松地将其放回到空闲池中,并可能与相邻的空闲块合并.
当你试图释放你没有从新收到的任何记忆时,那个簿记信息就不会存在,但是系统会像现在这样行事,结果将是不可预测的(通常很糟糕).
是的,它是未定义的行为:传递给delete
任何不是来自new
UB的东西:
C++标准,第3.7.3.2.3节:提供给标准库中提供的一个释放函数的第一个参数的值可以是
null
指针值; 如果是这样,并且如果解除分配函数是标准库中提供的函数,则对释放函数的调用不起作用.否则,operator delete(void*)
标准库中提供的值应为先前调用operator new(std::size_t)
或operator new(std::size_t, const std::nothrow_t&)
在标准库中调用返回的值之一.
未定义行为的后果是未定义的."没有任何事情发生"与其他任何事情一样有效.但是,它通常"没有立即发生":解除分配无效的内存块可能会在后续调用分配器时产生严重后果.
在Windows中使用g ++ 4.4后,我得到了非常有趣的结果:
在堆栈变量上调用delete似乎没有做任何事情.没有错误抛出,但删除后我可以毫无问题地访问变量.
如果一个类具有delete this
成功删除对象的类(如果它在堆中分配),但是如果它已在堆栈中分配(如果它在堆栈中,则没有任何反应).
没人知道会发生什么.这会调用未定义的行为,所以任何事情都可能发生.不要这样做.