我在
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 base\n"; } ~base(){ cout << "dtor of base\n"; } }; struct derived : base{ derived(){ cout << "ctor of derived\n"; } virtual ~derived(){ cout << "dtor of derived\n"; } }; 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}的大小恰好相同,因为分配空类的对象占用非零字节数,在两种情况下都恰好相同.