Bru*_*ton 98 c++ linker gcc kernel
这是来自操作系统开发网站的二手问题,但它让我很好奇,因为我无法在任何地方找到合适的解释.
使用gcc编译和链接独立的C++程序时,有时会出现这样的链接器错误:
out/kernel.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'
Run Code Online (Sandbox Code Playgroud)
这显然是因为这个符号是在libstdc ++中定义的,它在独立环境中是缺失的.解决问题只需要在某处定义此符号:
void *__gxx_personality_v0;
Run Code Online (Sandbox Code Playgroud)
这很好,但我不喜欢那些神奇地工作的东西......所以问题是,这个符号的目的是什么?
Ces*_*arB 90
它用在堆栈展开表中,您可以在我对另一个问题的答案的汇编输出中看到它.正如在该答案中所提到的,它的使用是由Itanium C++ ABI定义的,它被称为Personality Routine.
它通过将其定义为全局NULL void指针而"工作"的原因可能是因为没有任何东西抛出异常.当某些东西试图抛出异常时,你会发现它行为异常.
当然,如果没有使用异常,你可以用它们禁用它们-fno-exceptions(如果没有使用RTTI,你也可以添加-fno-rtti).如果您正在使用它们,您必须(如已经注明的其他答案)链接g++而不是gcc,这将为-lstdc++您添加.
Mar*_*wis 11
这是异常处理的一部分.gcc EH机制允许混合各种EH模型,并调用个性例程来确定异常是否匹配,要调用的终结等等.这个特定的个性例程用于C++异常处理(与gcj/Java相反)异常处理).
Joh*_*itb 11
异常处理包含在独立实现中.
这样做的原因是您可能使用gcc编译代码.如果使用该选项进行编译,-###则会-lstdc++在调用链接器进程时发现它缺少linker-option .编译g++将包括该库,因此包含在其中定义的符号.
libstd++代码库的快速grep 揭示了以下两个用法__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 *);
Run Code Online (Sandbox Code Playgroud)
在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 ...
}
Run Code Online (Sandbox Code Playgroud)
(注意:它实际上比这复杂一点;有一些条件编译可以改变一些细节).
所以,只要你的代码实际上没有使用异常处理,定义符号void*就不会影响任何东西,但是一旦它完成,你就会崩溃 - __gxx_personality_v0是一个函数,而不是一些全局对象,所以尝试调用该函数将跳转到地址0并导致段错误.
我有一次这个错误,我发现了原点:
我正在使用gcc编译器,我的文件被调用,CLIENT.C尽管我正在做一个C程序而不是C++程序.
gcc将.C扩展名识别为C++程序,.c扩展名为C程序(小心c和大C).
所以我重命名了我的文件CLIENT.c程序,它工作正常.