C++ __gxx_personality_v0 有什么用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/329059/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:41:08  来源:igfitidea点击:

What is __gxx_personality_v0 for?

c++gcclinkerkernel

提问by Bruce Johnston

This is a second-hand question from an OS development site, but it made me curious since I couldn't find a decent explanation anywhere.

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

When compiling and linking a free-standing C++ program using gcc, sometimes a linker error like this occurs:

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

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

This is apparently because this symbol is defined in libstdc++, which is missing in a free-standing environment. Fixing the problem simply requires defining this symbol somewhere:

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

void *__gxx_personality_v0;

Which is nice, but I don't like things that just magically work... So the question is, what is the purpose of this symbol?

这很好,但我不喜欢那些神奇的东西……所以问题是,这个符号的目的是什么?

采纳答案by CesarB

It is used in the stack unwiding tables, which you can see for instance in the assembly output of my answer to another question. As mentioned on that answer, its use is defined by the Itanium C++ ABI, where it is called the Personality Routine.

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

The reason it "works" by defining it as a global NULL void pointer is probably because nothing is throwing an exception. When something tries to throw an exception, then you will see it misbehave.

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

Of course, if nothing is using exceptions, you can disable them with -fno-exceptions(and if nothing is using RTTI, you can also add -fno-rtti). If you are using them, you have to (as other answers already noted) link with g++instead of gcc, which will add -lstdc++for you.

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

回答by Martin v. L?wis

It's part of the exception handling. The gcc EH mechanism allows to mix various EH models, and a personality routine is invoked to determine if an exception match, what finalization to invoke, etc. This specific personality routine is for C++ exception handling (as opposed to, say, gcj/Java exception handling).

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

回答by Johannes Schaub - litb

Exception handling is included in free standing implementations.

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

The reason of this is that you possibly use gccto compile your code. If you compile with the option -###you will notice it is missing the linker-option -lstdc++when it invokes the linker process . Compiling with g++will include that library, and thus the symbols defined in it.

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

回答by Adam Rosenfield

A quick grep of the libstd++code base revealed the following two usages of __gx_personality_v0:

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

In libsupc++/unwind-cxx.h

在 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 *);

In libsupc++/eh_personality.cc

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

(Note: it's actually a little more complicated than that; there's some conditional compilation that can change some details).

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

So, as long as your code isn't actually using exception handling, defining the symbol as void*won't affect anything, but as soon as it does, you're going to crash - __gxx_personality_v0is a function, not some global object, so trying to call the function is going to jump to address 0 and cause a segfault.

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

回答by jlguenego

I had this error once and I found out the origin:

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

I was using a gcc compiler and my file was called CLIENT.Cdespite I was doing a C program and not a C++ program.

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

gcc recognizes the .Cextension as C++ program and .cextension as C program (be careful to the small c and big C).

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

So I renamed my file CLIENT.cprogram and it worked.

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

回答by sagitta

The answers above are correct: it is used in exception handling. The manualfor GCC version 6 has more information (which is no longer present in the version 7 manual). The error can arise when linking an external function that - unknown to GCC - throws Java exceptions.

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