调用在s上分配的变量上的删除

忽略编程风格和设计,在堆栈上分配的变量上调用delete是“安全”的吗?

例如:

   int nAmount;
   delete &nAmount;

要么

class sample
{
public:
    sample();
    ~sample() { delete &nAmount;}
    int nAmount;
}
unistudent asked 2019-11-19T00:33:38Z
11个解决方案
98 votes

不,在堆栈分配的变量上调用free是不安全的。 您仅应在new创建的内容上致电delete[]

  • 对于每个freedelete[],应该恰好有一个new
  • 对于每个free,应该恰好有一个delete[]
  • 对于每个free,应该恰好有一个delete[]
  • 对于每个堆栈分配,都不应有显式的释放或删除。 如果适用,析构函数将自动调用。

通常,您不能混合搭配任何一种,例如 否free-ing或delete[]-ing new对象。 这样做会导致未定义的行为。

Mr Fooz answered 2019-11-19T00:34:30Z
46 votes

好吧,让我们尝试一下:

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

因此,显然这根本不安全。

Jeremy Ruten answered 2019-11-19T00:35:00Z
14 votes

请记住,当您使用new分配内存块(或为此分配malloc)时,实际分配的内存块将大于您的要求。该内存块还将包含一些簿记信息,以便您释放该块时,可以轻松地将其放回空闲池中,并可能与相邻的空闲块合并。

当您尝试释放新内存中没有收到的任何内存时,该簿记信息将不存在,但系统将按原样运行,结果将不可预测(通常很差)。

Ferruccio answered 2019-11-19T00:35:31Z
10 votes

是的,这是未定义的行为:UB传递给operator delete(void*)的任何不来自operator delete(void*)的东西都是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&)的调用返回的值之一。

不确定行为的后果是不确定的。 “什么都没有发生”与其他任何事情一样有效。 但是,通常通常“什么也不会立即发生”:取消分配无效的内存块可能会对随后的分配器调用产生严重的后果。

dasblinkenlight answered 2019-11-19T00:36:10Z
7 votes

在Windows中使用g ++ 4.4玩了一点之后,我得到了非常有趣的结果:

  1. 在堆栈变量上调用delete似乎没有任何作用。 没有错误抛出,但是删除后我可以毫无问题地访问变量。

  2. 如果类具有使用delete this的方法,则该对象将成功删除该对象(如果该对象已分配在堆中),但不会成功删除该对象(如果已在堆栈中分配该对象)(如果它在堆栈中,则什么也不会发生)。

Sambatyon answered 2019-11-19T00:36:49Z
5 votes

没人知道会发生什么。 这会调用未定义的行为,因此实际上任何事情都可能发生。 不要这样

answered 2019-11-19T00:37:13Z
4 votes

没有,使用new分配的内存应使用delete运算符删除使用malloc分配的分配应该使用free删除。并且无需取消分配在堆栈上分配的变量。

Vinay answered 2019-11-19T00:37:38Z
3 votes

天使失去了翅膀……您只能在分配了new的指针上调用delete,否则会出现不确定的行为。

Luchian Grigore answered 2019-11-19T00:38:04Z
1 votes

在这里,内存是使用堆栈分配的,因此无需从外部删除它,但是如果已动态分配

喜欢int * a = new int()

那么您必须删除a而不是删除&a(a本身是一个指针),因为内存是从空闲存储区分配的。

answered 2019-11-19T00:38:42Z
0 votes

您已经自己回答了这个问题。 delete必须仅用于通过new获得的指针。执行其他任何操作都是简单明了的未定义行为。

因此,实际上并没有说发生什么事情,从代码正常运行到崩溃到擦除硬盘驱动器都是有效的结果。 所以请不要这样做。

Grizzly answered 2019-11-19T00:39:16Z
0 votes

它是UB,因为您不得在尚未使用new动态分配的项目上调用delete。 就这么简单。

Martin James answered 2019-11-19T00:39:42Z
translate from https://stackoverflow.com:/questions/441831/calling-delete-on-variable-allocated-on-the-stack