调用堆栈上分配的variables的删除
忽略编程风格和devise,调用堆栈上分配的variables是否是“安全的”?
例如:
int nAmount; delete &nAmount;
要么
class sample { public: sample(); ~sample() { delete &nAmount;} int nAmount; }
不 ,在堆栈分配的variables上调用delete
是不安全的。 您应该只对new
东西调用delete
。
- 对于每个
malloc
或calloc
,应该只有一个free
。 - 对于每一个
new
应该只有一个delete
。 - 对于每个
new[]
,应该只有一个delete[]
。 - 对于每个堆栈分配,不应有明确的释放或删除。 在适用的情况下,析构函数被自动调用。
一般来说,你不能混合和匹配任何这些东西,例如没有free
或delete[]
一个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之后,我得到了非常有趣的结果:
-
调用堆栈variables的删除似乎没有做任何事情。 没有错误抛出,但我可以访问variables没有问题后删除。
-
如果在堆中分配一个具有
delete this
方法的类,则成功删除该对象,但是如果在堆中分配该对象(如果它在堆栈中,则不会发生任何变化)。
没有人能知道发生了什么事。 这调用了未定义的行为,所以可以发生任何事情。 不要这样做。
不,使用new分配的内存应该使用delete操作符来删除,使用malloc分配的内存应该使用free来删除。 而且不需要释放堆栈上分配的variables。
天使失去了翅膀……你只能用一个new
的指针调用delete
,否则你会得到未定义的行为。
这里的内存是使用堆栈分配的,所以不需要在外部删除它,但是如果你有全部的dynamic内容
像int * a = new int()
那么你必须删除一个而不是删除&a(一个本身就是一个指针),因为内存是从免费商店分配的。
你已经自己回答了这个问题。 delete
只能用于通过new
增加的指针。 做其他事情是简单明了的未定义的行为。
因此,真的没有什么话会发生什么,从代码工作正常到通过崩溃擦除硬盘驱动器的任何事情都是这样做的有效结果。 所以请不要这样做 。
这是UB,因为您不能使用新的dynamic分配的项目调用删除。 就这么简单。