gpt4 book ai didi

c++ - 为什么,真的,删除不完整的类型是未定义的行为?

转载 作者:IT老高 更新时间:2023-10-28 12:56:32 25 4
gpt4 key购买 nike

考虑这个用于解释前向声明做什么的经典示例:

//in Handle.h file
class Body;

class Handle
{
public:
Handle();
~Handle() {delete impl_;}
//....
private:
Body *impl_;
};

//---------------------------------------
//in Handle.cpp file

#include "Handle.h"

class Body
{
//Non-trivial destructor here
public:
~Body () {//Do a lot of things...}
};

Handle::Handle () : impl_(new Body) {}

//---------------------------------------
//in Handle_user.cpp client code:

#include "Handle.h"

//... in some function...
{
Handle handleObj;

//Do smtg with handleObj...

//handleObj now reaches end-of-life, and BUM: Undefined behaviour
}

我从标准中了解到,由于 Body 的析构函数并不简单,因此该案例将走向 UB。我试图理解的是真正的根本原因。

我的意思是,这个问题似乎是由 Handle 的 dtor 是内联的这一事实“触发”的,因此编译器会执行类似于以下“内联扩展”的操作(这里几乎是伪代码)。

inline Handle::~Handle()
{
impl_->~Body();
operator delete (impl_);
}

在所有翻译单元(在这种情况下只有 Handle_user.cpp)中,Handle 实例会被销毁,对吧?我只是无法理解:好的,当生成上述内联扩展时,编译器没有 Body 类的完整定义,但为什么它不能简单地让链接器解析 impl_->~Body( ) 的东西,所以让它调用 Body 的析构函数,实际上是在它的实现文件中定义的?

换句话说:我知道在句柄销毁时,编译器甚至不知道 Body 是否存在(非平凡的)析构函数,但为什么它不能像往常一样做,那是留下一个“占位符”供链接器填写,如果该功能真的不可用,最终有一个链接器“未解析的外部”?

我是否在这里遗漏了一些重要的东西(在这种情况下,我很抱歉这个愚蠢的问题)?如果不是这样,我只是想了解这背后的基本原理。

最佳答案

结合几个答案并添加我自己的,没有类定义调用代码不知道:

  • 该类是否具有已声明的析构函数,或者是否要使用默认析构函数,如果是,则默认析构函数是否微不足道,
  • 调用代码是否可以访问析构函数,
  • 存在哪些基类并具有析构函数,
  • 析构函数是否是虚拟的。实际上,虚函数调用使用与非虚函数不同的调用约定。编译器不能只是“发出代码来调用~Body”,而让链接器稍后处理细节,
  • (刚刚插入,感谢 GMan)delete 是否为类重载。

由于部分或全部原因,您不能在不完整类型上调用任何成员函数(加上另一个不适用于析构函数的原因 - 您不知道参数或返回类型)。析构函数也不异常(exception)。所以我不确定你说“为什么不能像往常一样?”是什么意思。

如您所知,解决方案是在定义 Body 的 TU 中定义 Handle 的析构函数,与定义所有其他成员函数的位置相同Handle 调用函数或使用 Body 的数据成员。然后在编译 delete impl_; 时,所有信息都可用于发出该调用的代码。

请注意,标准实际上是说,5.3.5/5:

if the object being deleted has incomplete class type at the point of deletion and the complete class has a non-trivial destructor or a deallocation function, the behavior is undefined.

我认为这是为了让你可以删除不完整的 POD 类型,就像你可以在 C 中 free 它一样。不过,如果你尝试它,g++ 会给你一个非常严厉的警告。

关于c++ - 为什么,真的,删除不完整的类型是未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2517245/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com