非法删除堆栈对象

时间:2013-08-02 12:38:54

标签: c++

int main()
{
    myClass obj;

    ....    /* doing things */
    ....

    delete &obj; /* illegal */
}

让我们假设myClass是一个适当的C ++类,其中包含所有内容。现在,我知道这是非法的,这个程序会在运行时崩溃。第一件事就是代码试图删除一个堆栈对象,然后在范围完成之后它再次被破坏。我想知道这种非法行动的内部情况。即删除会发生什么,它会调用析构函数吗?对你来说可能看起来很疯狂,但请帮助我理解。

4 个答案:

答案 0 :(得分:6)

行为未定义。会发生什么将取决于类的详细信息,正在发生的事情,程序的内存管理器是如何实现的,您使用的编译器,您正在运行的系统,以及可能还有许多其他我没有的东西花时间思考。这非常类似于询问化学品储罐爆炸时会发生什么的细节。

答案 1 :(得分:2)

你缺少一件重要的事情 - 除了调用析构函数之外,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 :(得分:1)

这是未定义的行为。标准,我们所有人生活和仰视的词语,说:

  

否则,提供给operator的值删除(void *)   标准库应该是前一个返回的值之一   调用operator new(size_t)或operator new(size_t,   标准库中的const std :: nothrow_t&amp;)

所以它是未定义的行为,任何事情都可能发生,并且它将取决于被错误删除的对象的实现,编译器,运气和其他事情。在内部询问“会发生什么”没有意义,因为任何事情都可能发生。最有可能的是,由于delete运算符假定您正确使用它,最终会在堆栈中引入一些不可预测的更改,这会使任何事情变得混乱。也许你以前的帧指针被覆盖,也许一些荒谬的返回值被推送到一个函数,也许被保存的寄存器被覆盖,因此尝试恢复寄存器状态会导致非常非法的情况。无论发生什么,都很难看。

答案 3 :(得分:0)

经验法则:

  

对于每个new,应该只有一个delete   对于每个new[],应该只有一个delete[]   对于每个malloccalloc,应该只有一个free   对于每个stack allocated对象,不应该有任何明确的删除。

其他任何内容都会导致未定义的行为


  

即。删除会发生什么,它会调用析构函数吗?

是的, delete 将首先调用对象析构函数。