110

这是来自操作系统开发站点的二手问题,但它让我感到好奇,因为我在任何地方都找不到合适的解释。

使用 gcc 编译和链接独立 C++ 程序时,有时会出现如下链接器错误:

out/kernel.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'

这显然是因为该符号是在 libstdc++ 中定义的,而独立环境中缺少该符号。解决这个问题只需要在某个地方定义这个符号:

void *__gxx_personality_v0;

这很好,但我不喜欢神奇地起作用的东西......所以问题是,这个符号的目的是什么?

4

6 回答 6

99

它用于堆栈展开表,例如,您可以在我对另一个问题的回答的汇编输出中看到它。正如那个答案所提到的,它的使用是由Itanium C++ ABI定义的,它被称为Personality Routine

通过将其定义为全局 NULL void 指针来“工作”的原因可能是因为没有抛出异常。当某些东西试图抛出异常时,你会看到它行为不端。

当然,如果没有使用异常,您可以禁用它们-fno-exceptions(如果没有使用 RTTI,您也可以添加-fno-rtti)。如果您正在使用它们,则必须(正如其他答案已经指出的那样)链接g++而不是gcc,这将为-lstdc++您添加。

于 2008-11-30T19:00:53.107 回答
12

这是异常处理的一部分。gcc EH 机制允许混合各种 EH 模型,并调用个性例程来确定异常是否匹配、调用什么终结等。这个特定的个性例程用于 C++ 异常处理(与 gcj/Java 相对)异常处理)。

于 2008-11-30T17:27:27.427 回答
12

异常处理包含在独立实现中。

这样做的原因是您可能使用它gcc来编译您的代码。如果您使用该选项进行编译,您会注意到它在调用链接器进程时-###缺少链接器选项。-lstdc++编译g++将包含该库,因此包含其中定义的符号。

于 2008-11-30T18:28:38.380 回答
6

对代码库的快速 greplibstd++揭示了以下两种用法__gx_personality_v0

在 libsupc++/unwind-cxx.h

// GNU C++ personality routine, Version 0.                                      
extern "C" _Unwind_Reason_Code __gxx_personality_v0
     (int, _Unwind_Action, _Unwind_Exception_Class,
      struct _Unwind_Exception *, struct _Unwind_Context *);

在 libsupc++/eh_personality.cc

#define PERSONALITY_FUNCTION    __gxx_personality_v0
extern "C" _Unwind_Reason_Code
PERSONALITY_FUNCTION (int version,
                      _Unwind_Action actions,
                      _Unwind_Exception_Class exception_class,
                      struct _Unwind_Exception *ue_header,
                      struct _Unwind_Context *context)
{
  // ... code to handle exceptions and stuff ...
}

(注意:实际上比这要复杂一些;有一些条件编译可以改变一些细节)。

因此,只要您的代码实际上没有使用异常处理,将符号定义为void*不会影响任何东西,但是一旦这样做,您就会崩溃 -__gxx_personality_v0是一个函数,而不是某个全局对象,所以尝试调用该函数将跳转到地址 0 并导致段错误。

于 2008-11-30T17:35:59.033 回答
6

我有一次这个错误,我发现了起源:

我正在使用 gcc 编译器,CLIENT.C尽管我正在执行 C 程序而不是 C++ 程序,但仍调用了我的文件。

gcc 将.C扩展识别为 C++ 程序,将扩展识别.c为 C 程序(注意小 c 和大 C)。

所以我重命名了我的文件CLIENT.c程序并且它起作用了。

于 2014-07-16T07:36:57.003 回答
2

上面的答案是正确的:它用于异常处理。GCC 版本 6的手册有更多信息(版本 7 手册中不再存在)。当链接一个 GCC 未知的外部函数会引发 Java 异常时,可能会出现该错误。

于 2018-03-03T21:42:03.540 回答