我在KDE软件中遇到过几个例子,其中dynamic_cast的KPart在OS上失败了。我并不是一个C++专家,所以我甚至不知道从哪里开始调试这种情况。我在ktimetracker中看到了这种情况,最近(也是讨论得更多的)案例是Okular:bug.cgi?id=345765
简而言之:Okular::Part类继承了Okular::ViewInterface类(作为列表中的最后一个父类)。然而,当代码检索Okular::Part*实例(part)时,dynamic_cast<Okular::ViewInterface*>(part)返回NULL。
上面BKO票证中的最后一点评论是,在这种情况下,使用静态强制转换将是一个糟糕的解决方案,但我应该尝试找出dynamic_cast失败的原因。这就引出了两个问题:
发布于 2015-04-11 20:28:44
让我解决这个问题的答案是蒂亚戈·马西埃拉()在Qt兴趣ML上提供的。我在这里复制它:
这类问题的常见怀疑是相同的:您的虚拟表没有正确地锚定在共享库中。 请确保参加此派对的所有类都选中以下所有框: *在类声明中有一个导出宏 *主虚拟函数位于.cpp中,从不内联 主虚拟函数是以父类的顺序排列的第一个新覆盖函数,如果没有重写,则是第一个新的虚拟函数。通常,多态类有虚拟析构函数,析构函数总是被覆盖,所以这是最好的选择。
在这种情况下,问题是由于目标类(Okular::ViewerInterface)没有在OS上导出(在默认情况下也可能是因为Linux上的全局编译器开关)。KDocumentViewer类的Idem,但这可能与此无关。
发布于 2015-04-06 10:57:26
这意味着指针所指向的对象在其继承层次结构中没有Okular::Part (我忽略了涉及多重继承的某些边缘情况)。因此,动态转换失败。
这就是它的意思。不过,它并不能真正帮助您理解最初引用的bug。
发布于 2015-04-06 11:25:01
除了这里的传统演员之外,dynamic_cast还能做些什么?
它执行运行时检查转换是否有效;指针确实指向正确类型的对象。
我怎么知道它为什么会失败呢?
如果Part确实是从ViewInterface派生的,那么如果指针指向有效的Part对象,则不会失败。所以这个物体一定是被破坏了。像瓦兰这样的动态分析工具可以帮助诊断这类问题。
这将是运行时的一个问题,libc++,不是吗?
几乎可以肯定不是。管理对象的生存期很可能是一个问题,结果是一个悬空指针。或者,它可能是某个其他地方的bug,破坏了对象,因此它不再包含有效的RTTI信息。或者,由于似乎涉及到线程,所以它可能是在没有足够的同步的情况下共享的。
静态石膏将是穷人的难题
这不会解决任何问题。通过不同的方式访问无效对象,您只会得到一种不同的未定义行为。
https://stackoverflow.com/questions/29469787
复制相似问题