O que é __gxx_personality_v0 para?

Esta é uma pergunta de segunda mão de um site de desenvolvimento de SO, mas me deixou curiosa, já que não consegui encontrar uma explicação decente em lugar algum.

Ao compilar e vincular um programa C ++ independente usando o gcc, às vezes ocorre um erro de vinculador como este:

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

Isto é aparentemente porque este símbolo é definido em libstdc ++, que está faltando em um ambiente independente. Consertar o problema simplesmente requer definir este símbolo em algum lugar:

 void *__gxx_personality_v0; 

O que é legal, mas eu não gosto de coisas que funcionam magicamente … Então a questão é, qual é o propósito desse símbolo?

Ele é usado nas tabelas de distribuição de pilha, que você pode ver, por exemplo, na saída da assembly da minha resposta para outra pergunta . Como mencionado nessa resposta, seu uso é definido pelo Itanium C ++ ABI , onde é chamado de Rotina de Personalidade .

A razão pela qual ele “funciona” definindo-o como um ponteiro void NULL global é provavelmente porque nada está lançando uma exceção. Quando alguma coisa tenta lançar uma exceção, você verá que ela se comportará mal.

Claro, se nada estiver usando exceções, você pode desativá-las com -fno-exceptions (e se nada estiver usando RTTI, você também pode adicionar -fno-rtti ). Se você os estiver usando, você deve (como outras respostas já mencionadas) linkar com g++ vez de gcc , o que adicionará -lstdc++ para você.

Faz parte do tratamento de exceções. O mecanismo gcc EH permite misturar vários modelos EH, e uma rotina de personalidade é invocada para determinar se uma exceção corresponde, qual finalização invocar, etc. Esta rotina de personalidade específica é para exception handling C ++ (em oposição a, digamos, gcj / Java exception handling).

O tratamento de exceções está incluído em implementações independentes.

A razão disso é que você possivelmente usa o gcc para compilar seu código. Se você compilar com a opção -### você notará que está faltando o linker-option -lstdc++ quando invoca o processo do linker. A compilation com g++ includeá essa biblioteca e, portanto, os símbolos definidos nela.

Um grep rápido da base de código libstd++ revelou os seguintes dois usos de __gx_personality_v0 :

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

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

(Nota: é na verdade um pouco mais complicado que isso; há alguma compilation condicional que pode mudar alguns detalhes).

Então, contanto que seu código não esteja realmente usando exception handling, definir o símbolo como void* não afetará nada, mas assim, você irá travar – __gxx_personality_v0 é uma function, não algum object global , então tentar chamar a function vai pular para o endereço 0 e causar um segfault.

Eu tive esse erro uma vez e descobri a origem:

Eu estava usando um compilador gcc e meu arquivo foi chamado CLIENT.C apesar de eu estar fazendo um programa C e não um programa C ++.

O gcc reconhece a extensão .C como programa C ++ e a extensão .c como programa C (tenha cuidado com o pequeno c e o grande C).

Então eu CLIENT.c meu programa CLIENT.c e funcionou.

As respostas acima estão corretas: são usadas no tratamento de exceções. O manual do GCC versão 6 contém mais informações (que não estão mais presentes no manual da versão 7). O erro pode surgir ao vincular uma function externa que – desconhecida do GCC – gera exceções Java.