关于VC8多继承的一个问题,是否是为实现多继承对象布局的bug?不知道是不是已经被发现了

WingForce 2008-12-06 10:48:34
struct _base1{};

struct _base2{};

struct _inheritance : _base1, _base2{};

int main()
{
// Ok no problem
_base1* p1 = new _inheritance;
delete p1;

// p2 now point to _base2 subobject, and the delete operator will cause error
_base2* p2 = new _inheritance;
delete p2;

return 0;
}


由于VC8实现多继承的机制,第二种情况下,p2的值会为了指向_base2类型的子对象,增加了1个byte,原因是_base2在继承列表中排列顺序在后,这也是多继承的一种实现机制,Insight C++ Object Module中也早已说明。可以通过使用/d1reportAllClassLayout编译选项观察到这一点,如下:
1>class _base1 size(1):
1> +---
1> +---
1>class _base2 size(1):
1> +---
1> +---
1>class _inheritance size(1):
1> +---
1> | +--- (base class _base1)
1> | +---
1> | +--- (base class _base2)
1> | +---
1> +---

也可以通过反汇编看到:
; this is the first case, p1 point to subobject _base1 which is just the address of _inheritance and no problem
00401000 push 1
00401002 call operator new (401048h)
00401007 push eax
00401008 call operator delete (40104Eh)

; this is the 2nd case, p2 point to subobject _base2 and ...
0040100D push 1
0040100F call operator new (401048h)
00401014 add esp,0Ch
00401017 test eax,eax
00401019 je wmain+2Ah (40102Ah)
0040101B add eax,1 ; here, for multi inheritance, the point add an offset of 1 to subobject _base2
0040101E push eax
0040101F call operator delete (40104Eh) ; and, the call to operator delete will cause error, the free failed.


因为观察到以上现象,很容易观察到是按照继承列表顺序,所以,试验了下面的情况

struct _inheritance : _base1, _base2, _base3 {};

_base3* p3 = new _inheritance;
delete p3;


果然也是这样。

多继承一直是C++实现的一个问题,所以,我猜测其他编译器也许有类似的或者其他问题,于是对GCC进行了测试,但是,GCC在这一点上没有问题。
...全文
56 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhyinty 2008-12-06
  • 打赏
  • 举报
回复
不知道,帮忙顶.
帅得不敢出门 2008-12-06
  • 打赏
  • 举报
回复
关系到this指针的偏移.
如果是空类的话,GCC没有问题,没有开辟多余的空间.
qqwx_1986 2008-12-06
  • 打赏
  • 举报
回复
等待牛人的进一步解说....

up
太乙 2008-12-06
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 WingForce 的回复:]
呃,得到答案了,C++标准认为这种情况下是没有定义的行为
如果需要正确析构,需要声明virtual的析构函器
http://forums.microsoft.com/china/AddPost.aspx?PostID=4215018&SiteID=15&ReturnUrl=
[/Quote]

如果不是使用rtti机制,那么程序的delete将在编译的时候确定下来该使用什么西沟函数!

对于lz的代码,由于delete编译时确定了是使用指针的静态类型来确定析构函数的调用!所以,会出问题~~
WingForce 2008-12-06
  • 打赏
  • 举报
回复
呃,得到答案了,C++标准认为这种情况下是没有定义的行为
如果需要正确析构,需要声明virtual的析构函器
http://forums.microsoft.com/china/AddPost.aspx?PostID=4215018&SiteID=15&ReturnUrl=

24,855

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧