【问题标题】:Dynamic cast (dynamic_cast) fails with .dylib on OSx (XCode)动态转换 (dynamic_cast) 在 OSx (XCode) 上使用 .dylib 失败
【发布时间】:2018-08-25 06:53:01
【问题描述】:

我正在构建一个由一个主要目标和几个插件组成的应用程序(在 OSx 案例中是 dylib)。我开始在这个项目上使用std::dynamic_pointer_cast 来转换并测试我的类层次结构中的特定类型。总的来说,这很好用,并且对于我的应用程序来说已经足够快了。

我现在的问题是,有时dynamic_castdynamic_pointer_cast 会在从插件中提取的代码部分中失败。我将dlopenRTLD_GLOBAL | RTLD_LAZY 一起使用,并且我还在用--export_dynamic 链接器标志编译我的主要目标,以确保所有符号都被拉入。但是,仍然有一些动态转换在不应该时失败。

我正在测试的类是多态的(虚拟析构函数),typeid(...).name() 总是返回一致的结果。然而,在某些情况下,动态转换返回 null,即使 typeid 信息看起来正确。

当我为调试而编译时,转换似乎总是成功(没有优化)。

我应该在插件或目标上对 OSx(XCode、clang)使用哪些其他链接器标志,以确保动态转换在我的情况下正常工作?

【问题讨论】:

  • 如果您希望人们能够帮助您,您应该发布 minimal reproducible example 来展示问题。
  • @JesperJuhl 谢谢。这个问题也只出现在我的发布版本中。但我会尝试整理一个干净的例子。
  • 您可能违反了单一定义规则,并且您继承的类实际上与您正在测试的类不同。跨可加载模块的类型标识不是一个简单的概念。

标签: c++ c++11 clang


【解决方案1】:

当您的应用程序还使用动态库 (.dylib) 时,我终于找到了确保 dynamic_cast 在 OSx 上正常工作的链接器设置。

我的问题:我与多个 dylib 共享一个库中的一些代码,然后使用动态转换来检查并从一种类型转换为另一种类型。然后在某些情况下(在 Release 下编译时)dynamic_cast(s) 会失败,即使 typeid(..).name() 确认我正在使用正确的类型。

我尝试使用dlopen(.., RTLD_GLOBAL) 加载我的插件,这应该允许动态库中定义的符号全局解析并可供其他插件使用。这并没有解决我的问题,尽管我确实将它保留在代码中,因为拥有它是有意义的。

我尝试将-export_dynamic 链接器标志添加到我的应用程序中,这应确保在使用dlopen 加载时所有全局符号都与动态库共享。同样,这并没有解决我的问题。

解决方案: 我终于遇到了一个参考,它说 Apple/BSD 对动态库使用两级符号名称解析,其中库本身被记录为符号解析的一部分。这可以通过-flat_namespace 链接器标志关闭。在我为所有插件添加此标志后,一切正常。

使用 -flat_namespace 链接器标志,我的所有 dynamic_casts 都按预期工作。

【讨论】:

    猜你喜欢
    • 2014-10-08
    • 1970-01-01
    • 2010-09-16
    • 2020-08-21
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多