C++ 在堆栈上分配的变量上调用删除
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/441831/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calling delete on variable allocated on the stack
提问by unistudent
Ignoring programming style and design, is it "safe" to call delete on a variable allocated on the stack?
忽略编程风格和设计,在堆栈上分配的变量上调用 delete 是否“安全”?
For example:
例如:
int nAmount;
delete &nAmount;
or
或者
class sample
{
public:
sample();
~sample() { delete &nAmount;}
int nAmount;
}
回答by Mr Fooz
No, it is not safe to call delete
on a stack-allocated variable. You should only call delete
on things created by new
.
不,调用delete
堆栈分配的变量是不安全的。你应该只调用delete
由new
.
- For each
malloc
orcalloc
, there should be exactly onefree
. - For each
new
there should be exactly onedelete
. - For each
new[]
there should be exactly onedelete[]
. - For each stack allocation, there should be no explicit freeing or deletion. The destructor is called automatically, where applicable.
- 对于每个
malloc
orcalloc
,应该正好有一个free
。 - 对于每个
new
应该有一个delete
。 - 对于每个
new[]
应该有一个delete[]
。 - 对于每个堆栈分配,不应有明确的释放或删除。在适用的情况下会自动调用析构函数。
In general, you cannot mix and match any of these, e.g. no free
-ing or delete[]
-ing a new
object. Doing so results in undefined behavior.
通常,您不能混合和匹配任何这些,例如 no free
-ing 或delete[]
-ing 一个new
对象。这样做会导致未定义的行为。
回答by Jeremy Ruten
Well, let's try it:
好吧,让我们试试看:
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
So apparently it is not safe at all.
所以显然它根本不安全。
回答by Ferruccio
Keep in mind that when you allocate a block of memory using new (or malloc for that matter), the actual block of memory allocated will be larger than what you asked for. The memory block will also contain some bookkeeping information so that when you free the block, it can easily be put back into the free pool and possibly be coalesced with adjacent free blocks.
请记住,当您使用 new(或 malloc)分配内存块时,实际分配的内存块将大于您要求的内存块。内存块还将包含一些簿记信息,以便在您释放该块时,可以轻松地将其放回空闲池中,并可能与相邻的空闲块合并。
When you try to free any memory that you didn't receive from new, that bookkeeping information wont be there but the system will act like it is and the results are going to be unpredictable (usually bad).
当您尝试释放未从 new 接收到的任何内存时,簿记信息将不存在,但系统将按原样运行,结果将是不可预测的(通常很糟糕)。
回答by dasblinkenlight
Yes, it is undefined behavior: passing to delete
anything that did not come from new
is UB:
是的,这是未定义的行为:传递给delete
任何不是来自new
UB 的东西:
C++ standard, section 3.7.3.2.3: The value of the first argument supplied to one of thea deallocation functions provided in the standard library may be a
null
pointer value; if so, and if the deallocation function is one supplied in the standard library, the call to the deallocation function has no effect. Otherwise, the value supplied tooperator delete(void*)
in the standard library shall be one of the values returned by a previous invocation of eitheroperator new(std::size_t)
oroperator new(std::size_t, const std::nothrow_t&)
in the standard library.
C++ 标准,第 3.7.3.2.3 节:提供给标准库中提供的 a 释放函数之一的第一个参数的值可能是
null
指针值;如果是这样,并且如果释放函数是标准库中提供的函数,则对释放函数的调用无效。否则,提供给operator delete(void*)
标准库中的值应是先前调用标准库中的任一者operator new(std::size_t)
或operator new(std::size_t, const std::nothrow_t&)
在标准库中返回的值之一。
The consequences of undefined behavior are, well, undefined. "Nothing happens" is as valid a consequence as anything else. However, it's usually "nothing happens right away": deallocating an invalid memory block may have severe consequences in subsequent calls to the allocator.
未定义行为的后果是未定义的。“什么都没有发生”与其他任何事情一样有效。然而,通常“没有立即发生任何事情”:释放无效内存块可能会在随后对分配器的调用中产生严重后果。
回答by Sambatyon
After playing a bit with g++ 4.4 in windows, I got very interesting results:
在 Windows 中使用 g++ 4.4 玩了一下之后,我得到了非常有趣的结果:
calling delete on a stack variable doesn't seem to do anything. No errors throw, but I can access the variable without problems after deletion.
Having a class with a method with
delete this
successfully deletes the object if it is allocated in the heap, but not if it is allocated in the stack (if it is in the stack, nothing happens).
在堆栈变量上调用 delete 似乎没有任何作用。没有错误抛出,但我可以在删除后毫无问题地访问该变量。
如果
delete this
对象在堆中分配,则具有方法的类成功删除该对象,但如果在堆栈中分配则不会(如果它在堆栈中,则不会发生任何事情)。
回答by Sambatyon
Nobody can know what happens. This invokes undefined behavior, so literally anything can happen. Don't do this.
没有人知道会发生什么。这会调用未定义的行为,因此实际上任何事情都可能发生。不要这样做。
回答by Vinay
No, Memory allocated using new should be deleted using delete operator and that allocated using malloc should be deleted using free. And no need to deallocate the variable which are allocated on stack.
不,使用 new 分配的内存应该使用 delete 操作符删除,使用 malloc 分配的内存应该使用 free 删除。并且不需要释放在堆栈上分配的变量。
回答by Luchian Grigore
An angel loses its wings... You can only call delete
on a pointer allocated with new
, otherwise you get undefined behavior.
天使失去了翅膀......你只能调用delete
分配了 的指针new
,否则你会得到未定义的行为。
回答by Luchian Grigore
here the memory is allocated using stack so no need to delete it exernally but if you have allcoted dynamically
这里的内存是使用堆栈分配的,因此无需从外部删除它,但如果您已动态分配
like int *a=new int()
像 int *a=new int()
then you have to do delete a and not delete &a(a itself is a pointer), because the memory is allocated from free store.
那么你必须做 delete a 而不是 delete &a(a 本身是一个指针),因为内存是从空闲存储分配的。
回答by Grizzly
You already answered the question yourself. delete
must only be used for pointers optained through new
. Doing anything else is plain and simple undefined behaviour.
你自己已经回答了这个问题。delete
只能用于通过 选择的指针new
。做任何其他事情都是简单明了的未定义行为。
Therefore there is really no saying what happens, anything from the code working fine through crashing to erasing your harddrive is a valid outcome of doing this. So please never do this.
因此,真的没有人说会发生什么,从代码正常运行到崩溃到擦除硬盘驱动器的任何事情都是这样做的有效结果。所以请永远不要这样做。