dynamic_cast失败 - 具体取决于操作系统版本
dynamic_cast fails - depending on OS Version
我有一个动态转换失败。类布局是这样的:
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下,侧播可以工作,在OSX 10.9下则不能(GCC 4.2使用动态c ++ stdlib)。使用 gdb 查看 vtable,我可以清楚地看到列出的 A2 方法和成员。
我的问题:
a) 侧播在技术上是否正确?它应该工作还是这是一个运行时错误?
b) 如果侧播依赖于运行时,那么这个运行时在哪里定义?我一直认为这是二进制文件的一部分?
c) 故障dynamic_cast是什么样的(在查看组装时),您如何追踪此类问题?
更新:这是我在系统控制台中看到的
15-11-01 14:16:27,435 APPNAMECHANGED[15280]:dynamic_cast错误 1:以下两个type_info都应该具有公开可见性。 其中至少有一个是隐藏的。10A1, 15A2.
所以 c) 得到了回答,至少对于 OSX 10.9。看看控制台。(Linux,有人吗?这看起来像是关于符号可见性的问题。医生说(gcc.gnu.org/wiki/Visibility)
然而,这不是故事的全部 - 它变得更加困难。默认情况下,符号可见性是"默认的",但如果链接器只遇到一个隐藏的定义 - 只有一个 - 该 typeinfo 符号将永久隐藏(请记住C++标准的 ODR - 一个定义规则)。这适用于所有符号,但更有可能影响您的类型信息;没有 vtable 的类的 typeinfo 符号是按需在使用类进行 EH 的每个对象文件中定义的,并且定义较弱,因此定义在链接时合并到一个副本中。
这就引出了下一个问题,
d) 我们如何追踪哪个符号至少被标记为隐藏一次,以及在哪里以及为什么?有没有检查 .o 文件的工具?
我们发现可执行文件链接到一个 dylib 之后,这个问题终于解决了,dylib 本身与 c++ 运行时静态链接,但使用不同的编译器(gcc 4.8 vs clang)编译。
免责声明:我只回答问题 a)。
首先,根据 [class.virtual]/1,B
显然是一个多态类型,因为它继承了一个虚函数(准确地说,B
继承了三个不同的函数)。
现在考虑 [expr.dynamic.cast]/8:
如果
C
是T
指向或引用的类类型,则运行时 检查逻辑执行如下:
- 如果,在派生最多的对象中,v指向(引用)到一个公共基类
C
对象的子对象,如果只有一个类型C
的对象派生自指向(引用)的子对象 通过v
结果指向(引用)该C
对象。- 否则,如果
v
指向(引用)派生最多的对象的公共基类子对象,以及派生最多的对象的类型 有一个基类,类型C
,它是明确和公共的, 结果点(引用)到派生最多的子对象的C
子对象 对象。- 否则,运行时检查将失败。
所以是的,它应该有效。
- 重载运算符new[]的行为取决于析构函数
- 在C++中设置基于操作系统的文件路径
- 新的放置取决于 iostream
- Writefile() 无法写入数据,具体取决于数据的长度
- 如何在工厂方法中返回指向基于基础操作系统的派生类的有效指针
- ASIO signal_set多个 IO 线程不可靠,具体取决于代码顺序?
- SFINAE是否取决于类型推断?
- 将强制转换简化为取决于参数的类型
- 修复"-Wunused-parameter"取决于预处理器条件的警告
- WideCharToMultiByte在英语操作系统上不转换日语
- 如何在 Windows 操作系统中在 geany 中安装插件
- 内存中类位置的成员是否取决于类成员在类定义中的位置?
- 操作系统平台支持宏和提升库
- 从utsname找出Linux操作系统名称
- 为什么 free() 函数不将内存返回给操作系统?
- 我可以让编译器忽略特定于操作系统的方法吗?
- 如何使用C预处理器生成可变大小(取决于操作系统)的十六进制文字
- 为什么在所有数据类型中,int 取决于操作系统或编译器
- dynamic_cast失败 - 具体取决于操作系统版本
- 浮点数大小取决于操作系统吗?