本文介绍了为什么在C ++中第二次调用析构函数未定义的行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如第二次调用析构函数已经是未定义的行为12.4 / 14(3.8)。

As mentioned in this answer simply calling the destructor for the second time is already undefined behavior 12.4/14(3.8).

例如: / p>

For example:

class Class {
public:
    ~Class() {}
};
// somewhere in code:
{
    Class* object = new Class();
    object->~Class();
    delete object; // UB because at this point the destructor call is attempted again
}

该类的设计方式使得析构函数可以被多次调用 - 不会发生类似双重删除的情况。内存仍然在 delete 被调用时分配 - 第一个析构函数调用不会调用 :: operator delete()释放内存。

In this example the class is designed in such a way that the destructor could be called multiple times - no things like double-deletion can happen. The memory is still allocated at the point where delete is called - the first destructor call doesn't call the ::operator delete() to release memory.

例如,在Visual C ++ 9中,上面的代码看起来工作正常。即使UB的C ++定义也不直接禁止被认为是UB的东西。因此,对于上面的代码打破一些实现和/或平台细节是必需的。

For example, in Visual C++ 9 the above code looks working. Even C++ definition of UB doesn't directly prohibit things qualified as UB from working. So for the code above to break some implementation and/or platform specifics are required.

为什么上述代码会中断和在什么条件下?

Why exactly would the above code break and under what conditions?

推荐答案

析构函数不是常规函数。调用一个不调用一个函数,它调用许多函数。它的破坏的魔力。虽然你提供了一个简单的析构函数,唯一的目的是使它很难显示它可能如何破坏,但你没有证明什么是被调用的其他函数。标准也没有。

Destructors are not regular functions. Calling one doesn't call one function, it calls many functions. Its the magic of destructors. While you have provided a trivial destructor with the sole intent of making it hard to show how it might break, you have failed to demonstrate what the other functions that get called do. And neither does the standard. Its in those functions that things can potentially fall apart.

作为一个简单的例子,让我们说编译器插入代码来跟踪对象生命周期以进行调试目的。构造函数[它也是一个魔术函数,做所有你没有要求的东西]将一些数据存储在我在这里。在析构函数被调用之前,它改变数据,说我去了。调用析构函数后,它会去掉用于查找数据的信息。因此,下次调用析构函数时,最终会出现访问冲突。

As a trivial example, lets say the compiler inserts code to track object lifetimes for debugging purposes. The constructor [which is also a magic function that does all sorts of things you didn't ask it to] stores some data somewhere that says "Here I am." Before the destructor is called, it changes that data to say "There I go". After the destructor is called, it gets rid of the information it used to find that data. So the next time you call the destructor, you end up with an access violation.

您可能还想出了涉及虚拟表的示例,但示例代码didn不包括任何虚拟函数,以便作弊。

You could probably also come up with examples that involve virtual tables, but your sample code didn't include any virtual functions so that would be cheating.

这篇关于为什么在C ++中第二次调用析构函数未定义的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-21 13:44