dynamic_cast失败意味着什么

What does it mean when a dynamic_cast fails?

本文关键字:意味着 什么 失败 cast dynamic      更新时间:2023-10-16

我在KDE软件中遇到过一些情况,即KPart的dynamic_cast在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失败的原因。这就引出了两个问题:

  • dynamic_cast除了传统的cast之外还有什么功能
  • 我该如何弄清楚它为什么会失败?这将是运行时的问题,libc++,不是吗

让我解决问题的答案是由Thiago Macieira在Qt Interest ML上提供的。我将其复制到这里:

通常的嫌疑犯问题是一样的:您的虚拟表没有正确地锚定在共享库。

请确保参与此聚会的所有类都选中所有这些框:
*在类声明中具有导出宏
*主要的虚拟函数在.cpp、NEVER内联中

主虚拟函数是父类的顺序,或者,如果没有重写,则为第一个新虚拟。通常,多态类有虚拟析构函数,析构函数是总是被覆盖,所以这是你最好的选择。

在这种情况下,问题是由于目标类(Okular::ViewerInterface)没有在OSX上导出(可能是默认情况下,或者是由于Linux上的全局编译器开关)。KDocumentViewer类的Idem,但这可能并不相关。

这意味着指针所指向的对象在其继承层次结构中没有Okular::Part(我忽略了某些涉及多重继承的边缘情况)。因此,动态强制转换失败。

这就是它的意思。不过,它并不能真正帮助您理解最初引用的bug。

dynamic_cast除了传统的cast之外还有什么功能?

它执行运行时检查转换是否有效;指针确实指向正确类型的对象。

我该如何弄清楚它为什么会失败?

如果Part真的是从ViewInterface派生的,那么如果指针指向有效的Part对象,它就不会失败。所以这个对象一定是被破坏了。像Valgrind这样的动态分析工具可以帮助诊断这类问题。

这将是运行时的问题,libc++,不是吗?

几乎可以肯定不是。这很可能是管理对象生存期的问题,最终导致指针悬空。或者可能是其他地方的错误损坏了对象,使其不再包含有效的RTTI信息。或者,由于似乎有线程参与,可能是在没有充分同步的情况下共享的。

静态铸造将是一个穷人的修复

它不会解决任何问题。通过以不同的方式访问无效对象,您只会得到不同风格的未定义行为。