我有一个失败的动态演员。班级布局是这样的:
class A1
{
    public:
virtual int foo1()=0;
};
class A2
{
    public:
    virtual int foo2();
};
class A3
{
public:
   virtual int foo3();
};
class B : public A1, public A2, public A3 
{
   int bar();
};
现在我使用指针(因此不会发生切片)进行向下转换。
main()
{
   B b;
   A1* a1 = dynamic_cast<A1*> (&b); // ok
   B*  b1 = dynamic_cast<B*>  (a1); // ok
   A2* a2_1 = dynamic_cast<A2*> (a1); // OSX 10.7 ok, OSX 10.9 fail
   A2* a1_2 = dynamic_cast<A2*> (b1); // ok
};
向下倾斜有效,向上倾斜有效,但侧倾并不总是有效。在 OSX 10.7 下,sidecast 工作,在 OSX 10.9 下它不工作(GCC 4.2 使用动态 c++ stdlib)。使用 gdb 查看 vtable 我可以清楚地看到列出的 A2 方法和成员。
我的问题:
a) 侧播在技术上是否正确?它应该工作还是这是一个运行时错误?
b) 如果 sidecast 依赖于运行时,那么这个运行时是在哪里定义的?我一直以为这是二进制文件的一部分?
c) 失败的 dynamic_cast 看起来如何(在查看程序集时),您如何追踪此类问题?  
更新:这是我在系统控制台中看到的
11/01/15 14:16:27,435 APPNAMECHANGED[15280]:dynamic_cast 错误 1:以下两个 type_info 都应该公开。其中至少有一个是隐藏的。10A1、15A2。
所以 c) 得到了回答,至少对于 OSX 10.9。看看控制台。(Linux,有人?)它看起来像一个关于符号可见性的问题。Doc 说 (gcc.gnu.org/wiki/Visibility)
然而,这还不是全部——它变得更难了。默认情况下,符号可见性是“默认”,但如果链接器只遇到一个隐藏的定义 - 只有一个 - 该 typeinfo 符号将永久隐藏(请记住 C++ 标准的 ODR - 一个定义规则)。这适用于所有符号,但更有可能通过 typeinfos 影响您;没有 vtable 的类的 typeinfo 符号是根据需要在每个使用 EH 类的对象文件中定义的,并且定义很弱,因此定义在链接时合并为一个副本。
这就引出了下一个问题,
d) 我们如何追踪哪个符号至少被标记为隐藏一次,以及在哪里以及为什么?是否有检查 .o 文件的工具?
| 归档时间: | 
 | 
| 查看次数: | 2250 次 | 
| 最近记录: |