什么是__gxx_personality_v0?

这是来自操作系统开发网站的第二手问题,但这让我很好奇,因为我无法在任何地方find一个合适的解释。

当使用gcc编译和链接一个独立的C ++程序时,有时会出现这样的链接器错误:

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

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

 void *__gxx_personality_v0; 

这是好的,但我不喜欢神奇的工作…所以问题是,这个符号的目的是什么?

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

通过将其定义为全局NULL空指针“工作”的原因可能是因为没有任何内容抛出exception。 当有东西试图抛出exception,那么你会看到它的行为不端。

当然,如果什么都没有使用exception,你可以用-fno-exceptions来禁用它们(如果没有使用RTTI,你也可以添加-fno-rtti )。 如果你正在使用它们,你必须(如其他答案已经注意到)链接到g++而不是gcc ,它会为你添加-lstdc++

这是exception处理的一部分。 gcc EH机制允许混合各种EH模型,调用个性例程以确定是否匹配exception,调用什么定式等。这个特定的个性例程用于C ++exception处理(与gcj / Java相反exception处理)。

exception处理包含在独立实现中。

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

libstd++代码库的一个简单的grep显示了libstd++的两个用法:

在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 ... } 

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

所以,只要你的代码实际上没有使用exception处理,将符号定义为void*不会影响任何东西,但是一旦它发生,你将会崩溃 – __gxx_personality_v0是一个函数,而不是一些全局对象,所以试图调用函数将跳转到地址0并导致段错误。

我有这个错误一次,我发现了原点:

我正在使用gcc编译器,我的文件被称为CLIENT.C尽pipe我正在做一个C程序,而不是一个C ++程序。

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

所以我重命名我的文件CLIENT.c程序,它的工作。