0
int main()
{
    myClass obj;

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

    delete &obj; /* illegal */
}

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

4

4 回答 4

6

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

于 2013-08-02T12:44:54.520 回答
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++ 类对象释放内存时,对象的析构函数在对象的内存被释放之前被调用(如果对象有析构函数)。

于 2013-08-02T12:43:09.843 回答
1

这是未定义的行为。标准,我们所有人赖以生活和仰望的话语,它说:

否则,在标准库中提供给 operator delete(void*) 的值应是先前调用标准库中 operator new(size_t) 或 operator new(size_t, const std::nothrow_t&) 返回的值之一

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

于 2013-08-02T12:49:36.717 回答
0

经验法则:

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

其他任何事情都会导致未定义的行为


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

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

于 2013-08-02T12:43:57.447 回答