加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 当派生类的析构函数是虚拟的而代码崩溃时,基类’dtor不是

发布时间:2020-12-16 03:07:10 所属栏目:百科 来源:网络整理
导读:我在 gcc 4.4.5上尝试了以下代码. 如果成员’data’不存在,则代码执行正常,但在其存在时,它会崩溃.当派生类’dtor不是虚拟的时,它也不会崩溃. 我知道在这两种情况下,行为都是未定义的,如C 03(5.3.5 / 3)中所列,但仍有人可以向我提供一些解释,为什么在后一种
我在 gcc 4.4.5上尝试了以下代码.

如果成员’data’不存在,则代码执行正常,但在其存在时,它会崩溃.当派生类’dtor不是虚拟的时,它也不会崩溃.

我知道在这两种情况下,行为都是未定义的,如C 03(5.3.5 / 3)中所列,但仍有人可以向我提供一些解释,为什么在后一种情况下会崩溃?

是的,我知道UB意味着任何事情都可能发生,但我仍然想知道特定于实现的细节.

#include<iostream>    
using std::cout;

struct base{
int data;
   base(){
      cout << "ctor of basen";
   }
   ~base(){
      cout << "dtor of basen";
   }
};

struct derived :  base{
   derived(){
      cout << "ctor of derivedn";
   }
   virtual ~derived(){
      cout << "dtor of derivedn";
   }
};

int main(){
   base *p = new derived;
   delete p;
}

解决方法

假设在我的系统上发生了什么(gcc 4.6.0,linux x86_64)与你的系统发生了什么(它也与数据崩溃并且没有运行),实现细节是p没有指向内存块的开头为派生类型的对象分配.

正如瓦格林德告诉我的那样,

Address 0x595c048 is 8 bytes inside a block of size 16 alloc'd

如果您打印指针的值,您可以自己看到:

derived * d = new derived;
std::cout << d << 'n';
base *p = d;
std::cout << p << 'n';

原因是gcc中的对象布局是{vtable,base,derived}

当base为空时,{vtable,derived}和{base}的大小恰好相同,因为分配空类的对象占用非零字节数,在两种情况下都恰好相同.

当派生没有虚函数时,vtable不存在,地址再次相同,删除成功.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读