uni*_*ent 56 c++ heap stack delete-operator
忽略编程风格和设计,在堆栈上分配的变量上调用delete是"安全的"吗?
例如:
int nAmount;
delete &nAmount;
Run Code Online (Sandbox Code Playgroud)
要么
class sample
{
public:
sample();
~sample() { delete &nAmount;}
int nAmount;
}
Run Code Online (Sandbox Code Playgroud)
Mr *_*ooz 102
不,调用delete堆栈分配的变量是不安全的.你应该只调用delete创建的东西new.
malloc或者calloc,应该只有一个free. new应该只有一个delete. new[]应该只有一个delete[]. 在一般情况下,你不能随意搭配任何这些,例如没有free-ing或delete[]-ing一个new对象.这样做会导致未定义的行为.
Jer*_*ten 49
好吧,我们来试试吧:
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
Run Code Online (Sandbox Code Playgroud)
显然它根本不安全.
Fer*_*cio 14
请记住,当您使用new(或malloc)分配内存块时,分配的实际内存块将大于您的要求.内存块还将包含一些簿记信息,以便在释放块时,可以轻松地将其放回到空闲池中,并可能与相邻的空闲块合并.
当你试图释放你没有从新收到的任何记忆时,那个簿记信息就不会存在,但是系统会像现在这样行事,结果将是不可预测的(通常很糟糕).
das*_*ght 10
是的,它是未定义的行为:传递给delete任何不是来自newUB的东西:
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成功删除对象的类(如果它在堆中分配),但是如果它已在堆栈中分配(如果它在堆栈中,则没有任何反应).
小智 5
没人知道会发生什么.这会调用未定义的行为,所以任何事情都可能发生.不要这样做.