【问题标题】:Why can I catch an object or dynamic_cast even if its std::type_info object is different?为什么即使 std::type_info 对象不同,我也能捕获对象或 dynamic_cast?
【发布时间】:2015-11-25 19:15:16
【问题描述】:

我正在进行一项实验,并在我从程序中打开的程序和共享库中定义了相同的类,并确保程序在其动态表中没有类型信息对象的条目。然后我从共享库中抛出该类的一个对象,并尝试使用相同的类类型来捕获它。

我预计 linux 和 gcc 上的实现不会捕获异常,因为程序和共享库中两个类的类型信息对象不同,因此只有在运行时进行字符串比较时才有可能匹配损坏的类名。

它仍然匹配,我什至可以对共享库中定义的类进行动态向下转换。谁能解释一下在这种情况下实现是如何工作的?

编辑

根据 Itanium ABI 的规定,观察到的行为似乎不符合标准。我在这里错过了什么?

因此,除了指向不完整类型的直接或间接指针外,等式和不等式运算符在对那些 type_info 对象进行操作时可以写成地址比较:两个 type_info 结构描述相同的类型当且仅当它们是相同的结构 (在同一个地址)。

由于两个 typeinfo 有不同的地址,因此描述的结构代表不同的类型。因此,强制转换应该失败并且不应该捕获异常。

【问题讨论】:

  • dlopen-ed模块中类内的静态成员是否与同源级名称的类内的静态成员合并?

标签: c++ exception-handling shared-libraries typeid itanium-abi


【解决方案1】:

Itanium ABI 明确声明按重整名称比较类的 type_info 对象,这确实是您问题中假设的实现。

https://refspecs.linuxbase.org/cxxabi-1.86.html#rtti

我想这里的理由是完全支持您观察到的行为。

typeinfo 描述符也被定义为具有“模糊链接”,这很可爱。但是,使用的定义要求将它们放在 COMDAT 组中。 COMDAT 组需要由链接器进行重复数据删除,至少作为静态链接的一部分。我目前无法确定是否也需要对它们进行重复数据删除以进行动态链接,但这似乎合乎逻辑。

因此,总而言之,您的问题的答案是“已处理,因为 ABI 作者预见到了这种情况并确保已处理”。

【讨论】:

  • 谢谢。嗯,从我读到的,似乎表明地址必须相同(注意 iff):“因此,除了指向不完整类型的直接或间接指针外,相等和不等运算符可以写为地址比较时对那些 type_info 对象进行操作:两个 type_info 结构描述相同的类型当且仅当它们是相同的结构(在相同的地址)。”
  • stackoverflow.com/questions/5044993/… 似乎不同意你的回答。
  • 没有 RTLD_GLOBAL 标志,模块实际上是两个不同的程序,因此限制不适用,因为它只考虑一个程序。您可以在此处查看其他违反规范的情况,例如同一函数有两个定义。
【解决方案2】:

在程序和我从程序中打开的共享库中定义了相同的类 - 恭喜您违反了一个定义规则。在未定义行为的土地上,任何事情都可能发生,你应该知道。

【讨论】:

  • 为什么会违反 ODR?我认为这就是为什么我们有头文件,在程序中我们需要的任何 obj 文件中定义类。你还想怎么定义一个接口?
  • 您有一个标题但有多个定义:一个在您的应用程序中,一个在您的库中。在您的程序或库中应该有一个定义。不是都。一种解决方案是将公共类放在一个共享库中并为它们使用动态链接。
  • @gui 所有成员函数都是内联的。所以我在这里没有看到违规行为。但由于这是共享库的疯狂,而且 C++ 标准不了解共享库,我认为即使函数是非内联的,我们也不能说这会违反 ODR。通常 linux elf 共享对象支持存在多个定义。
  • @ᐅJohannesSchaub-litbᐊ,这是违反 ODR 的。您的课程在两个地方定义。并且内联或非内联没有轴承听到。这种违规(由dlopening 产生)是非常微妙且难以追踪的错误的已知原因。您最近才真正处理了类似性质的生产核心转储 - 在应用程序和它dlopened 的共享库之一中定义的全局静态对象。
  • 这些对象不同于实现定义的隐藏对象。该标准不允许用户发布 typeinfo 结构定义,或指定它们的链接;因此,是否处理这种情况取决于实现。
猜你喜欢
  • 1970-01-01
  • 2017-04-22
  • 1970-01-01
  • 1970-01-01
  • 2010-10-06
  • 2011-10-11
  • 2020-08-30
  • 1970-01-01
  • 2011-06-28
相关资源
最近更新 更多