非法删除堆栈对象[重复]
Posted
技术标签:
【中文标题】非法删除堆栈对象[重复]【英文标题】:Illegal deletion of a stack object [duplicate] 【发布时间】:2013-08-03 17:38:05 【问题描述】:int main()
myClass obj;
.... /* doing things */
....
delete &obj; /* illegal */
让我们假设 myClass 是一个适当的 C++ 类,一切都已就绪。现在,我知道这是非法的,这个程序会在运行时崩溃。第一件事是代码试图删除一个堆栈对象,然后在范围完成后再次删除它。我想知道这个非法操作的内部情况。即删除会发生什么,它会调用析构函数吗?你可能看起来很疯狂,但请帮助我理解。
【问题讨论】:
它会可能崩溃,但与未定义行为的情况一样,另一方面,它可能不会崩溃,或者大多数时间但并非总是崩溃,或者甚至导致nasal demons。更重要的是你的问题,真的没有办法告诉这将如何处理,未定义行为的性质在大多数情况下是不可预测的。 通过检查非优化构建中生成的代码,不难发现它的实际作用 这不是骗子。这里的 OP 不是问它是否安全,他们知道它不安全。 @jrok 该线程的答案仍然 100% 适用于这个问题:这是未定义的行为。 【参考方案1】:你错过了一件重要的事情——除了调用析构函数之外,delete
将释放分配给new
的内存并将其返回到堆中。在堆栈分配的变量上调用 free 是不安全的。要查看它是否会首先调用析构函数,只需将一些 cout
放入 myClass
析构函数 - 在我的配置中它在分段错误之前调用析构函数。
#include <iostream>
using namespace std;
class myClass
public:
~myClass() cout << "Destructor" << endl;
;
int main()
myClass A;
delete &A;
cout << "End of main\n";
return 0;
来自MSDN:
当 delete 用于为 C++ 类对象释放内存时,在释放对象内存之前调用对象的析构函数(如果对象具有析构函数)。
【讨论】:
【参考方案2】:经验法则:
对于每个
new
,应该恰好有一个delete
。 对于每个new[]
,应该恰好有一个delete[]
。 对于每个malloc
或calloc
,应该恰好有一个free
。 对于每个stack allocated
对象,不应有任何显式删除。
其他任何事情都会导致未定义的行为。
即删除会发生什么,它会调用析构函数吗?
是的,delete会先调用对象的析构函数。
【讨论】:
【参考方案3】:行为未定义。会发生什么将取决于类的细节、发生了什么、程序的内存管理器是如何实现的、您使用的编译器、您正在运行的系统,以及可能还有许多其他我没有做的事情花时间去想。这很像询问化学品储罐爆炸时会发生什么的细节。
【讨论】:
【参考方案4】:这是未定义的行为。标准,我们所有人赖以生存和尊重的话语,它说:
否则,提供给运算符 delete(void*) 的值 标准库应是前一个返回的值之一 调用 operator new(size_t) 或 operator new(size_t, 标准库中的 const std::nothrow_t&)
所以这是未定义的行为,任何事情都可能发生,这取决于被错误删除的对象的实现、编译器、运气和其他因素。在内部询问“发生了什么”是没有意义的,因为任何事情都可能发生。最有可能的是,由于 delete
运算符假定您正确使用它,您最终会在堆栈中引入一些不可预测的更改,这可能会搞砸任何事情。也许你之前的帧指针被覆盖,也许一些荒谬的返回值被推送到一个函数,也许保存的寄存器被覆盖,所以尝试恢复寄存器状态会导致非常非法的情况。不管发生什么,都是丑陋的。
【讨论】:
以上是关于非法删除堆栈对象[重复]的主要内容,如果未能解决你的问题,请参考以下文章