【问题标题】:Why doesn't defining `__cxa_throw` cause a link error?为什么定义 `__cxa_throw` 不会导致链接错误?
【发布时间】:2021-04-22 07:04:48
【问题描述】:

为什么下面的C++程序与系统提供的__cxa_throw没有链接冲突?

#include <cstring>

void __cxa_throw(void *, void *, void (*)(void *)) {
    std::puts("bad luck");
}

int main() {
    throw 13;
}

这个符号有什么神奇之处吗?对于正常功能,这将违反 ODR,不是吗?

【问题讨论】:

  • 运行时提供的函数可能是extern "C",而你的函数名却是乱码。无论如何,这个程序通过使用保留名称表现出未定义的行为。
  • ODR: "...不需要编译器来诊断此违规行为,但违反它的程序的行为未定义..." en.cppreference.com/w/cpp/language/definition
  • @IgorTandetnik:用extern "C" 尝试过,仍然有效,没有链接错误。
  • @RichardCritten:当然,但是对于其他符号,它确实会导致链接错误 - 所以我的问题是为什么不是这个?
  • 你不能定义任何以双下划线开头的符号。这些符号是为编译器和标准库保留的。 stackoverflow.com/a/224420/1387438

标签: c++ linux gcc c++17 libstdc++


【解决方案1】:

正如@Igor 指出的那样,您需要添加extern "C" 以防止名称错误。

但它起作用的原因是因为该符号很可能被定义为。这意味着如果您重新定义它,链接器将使用您的版本而不是标准的库。

Gcc's source code 确认他们将其定义为弱。 我不确定原因,也许是与共享库的内部兼容性等等...... 实际上,在我不知何故错过的定义上方有一条评论:

77 /* Everything from libstdc++ is weak, to avoid requiring that library
   to be linked into plain C applications using libitm.so.  */

原来如此。

不言而喻,这样做真的很糟糕,甚至没有适当的文档说明其他函数期望 __cxa_throw 做什么。

【讨论】:

  • 谢谢。我想知道为什么__cxa_throw 被定义为弱。有人知道吗?
  • @AndrewTomazos 我在函数定义的正上方找到了一条评论,编辑了答案。不知怎的,我第一次错过了它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-29
  • 2015-05-20
  • 1970-01-01
  • 2011-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多