什么是__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
程序,它的工作。