我在KDE软件中遇到过一些案例,其中一个KPart的动态广播在OS X上失败了。我不是那么多C ++专家,所以我甚至不知道从哪里开始调试这样的一种情况。 我已经看到ktimetracker会发生这种情况,最新的(也是讨论得更好的)案例是Okular:https://bugs.kde.org/show_bug.cgi?id=345765
简而言之:Okular::Part
类继承Okular::ViewInterface
类(作为列表中的最后一个父级)。但是,当代码检索Okular::Part*
实例(part
)时,dynamic_cast<Okular::ViewInterface*>(part)
将返回NULL。
上面BKO票的最后一个评论是在这种情况下使用静态强制转换将是一个穷人的修复,但我应该试图找出dynamic_cast失败的原因。这引出了两个问题:
答案 0 :(得分:1)
这意味着指针所指向的对象在其继承层次结构中没有Okular::Part
(我忽略了涉及多重继承的某些边缘情况)。因此,动态演员失败。
这就是它的含义。但是,它并没有真正帮助你理解最初引用的bug。
答案 1 :(得分:1)
除了传统演员之外,dynamic_cast还会做什么?
执行转换有效的运行时检查;指针确实指向了正确类型的对象。
我怎么知道它失败的原因?
如果Part
确实来自ViewInterface
,那么如果指针指向有效的Part
对象,它就不会失败。因此,对象必须已被破坏或破坏。像Valgrind这样的动态分析工具可以帮助诊断这类问题。
这将是运行时问题,libc ++,没有?
几乎肯定不是。这很可能是管理对象生命周期的问题,最后是悬空指针。或者它可能是其他地方破坏对象的错误,因此它不再包含有效的RTTI信息。或者,由于似乎涉及线程,可能是在没有充分同步的情况下共享它。
静态演员将是一个穷人的解决方案
它无法解决任何问题。您只是以不同的方式访问无效对象,从而获得不同类型的未定义行为。
答案 2 :(得分:1)
Thiago Macieira在Qt Interest ML上提供了解决问题的答案。我在这里复制它:
这是通常的嫌疑人 问题是一样的:您的虚拟表没有正确锚定 共享库。确保参加此方的所有课程都检查所有这些方框:
*在班级申报中有一个出口宏 *主要虚拟功能是.cpp,NEVER inline主虚函数是第一个新重写函数 父类的顺序,或者,如果没有被覆盖,则为第一个新虚拟。 通常,多态类具有虚拟析构函数和析构函数 总是被覆盖,所以这是你最好的选择。
在这种情况下,问题是由于目标类(Okular :: ViewerInterface)未在OS X上导出(可能是默认情况下,或者是因为Linux上的全局编译器开关)。请注意KDocumentViewer类,但这可能不相关。