dynamic_cast 失败是什么意思?

What does it mean when a dynamic_cast fails?

我在 KDE 软件中遇到过一些情况,其中 dynamic_cast 的 KPart 在 OS X 上失败。我不是 C++ 专家,所以我不会甚至不知道从哪里开始调试这样的情况。 我已经看到这种情况发生在 ktimetracker 上,最新的(也是讨论得更好的)案例是关于 Okular 的:https://bugs.kde.org/show_bug.cgi?id=345765

简而言之:Okular::Part class 继承了 Okular::ViewInterface class(作为列表中的最后一个父级)。然而,当代码检索到 Okular::Part* 实例 (part) 时,dynamic_cast<Okular::ViewInterface*>(part) returns NULL.

上面 BKO 票证中的最后一条评论是,在这种情况下使用静态转换将是一个穷人的解决方案,但我应该设法找出 dynamic_cast 失败的原因。这让我想到了 2 个问题:

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

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

what does a dynamic_cast do in addition to a traditional cast here?

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

how would I figure out why it fails?

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

This would be an issue with the runtime, libc++, no?

几乎可以肯定不是。这很可能是管理对象生命周期的问题,最终会出现悬空指针。或者它可能是其他地方的错误破坏了对象,因此它不再包含有效的 RTTI 信息。或者,由于似乎涉及线程,也许它在没有充分同步的情况下被共享。

static cast would be a poor man's fix

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

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

the usual suspect in this kind of problem is the same: your virtual tables are not properly anchored in shared libraries.

Make sure that all classes participating in this party check all these boxes:
* have an export macro in the class declaration
* the primary virtual function is in a .cpp, NEVER inline

The primary virtual function is the first newly overriden function in the parent classes' order or, if none are overridden, the first new virtual. Usually, polymorphic classes have virtual destructors and destructors are always overridden, so this is your best bet.

在这种情况下,问题是由于目标 class (Okular::ViewerInterface) 未在 OS X 上导出(可能是默认情况下或由于全局编译器打开 Linux)。同上 KDocumentViewer class,但这可能不相关。