Pregunta ¿Para qué es __gxx_personality_v0?


Esta es una pregunta de segunda mano de un sitio de desarrollo de SO, pero me dio curiosidad ya que no pude encontrar una explicación decente en ninguna parte.

Al compilar y vincular un programa autónomo de C ++ utilizando gcc, a veces se produce un error de enlazador como este:

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

Aparentemente, esto se debe a que este símbolo está definido en libstdc ++, que falta en un entorno libre. La solución del problema simplemente requiere definir este símbolo en alguna parte:

void *__gxx_personality_v0;

Lo cual es bueno, pero no me gustan las cosas que solo funcionan mágicamente ... Entonces la pregunta es, ¿cuál es el propósito de este símbolo?


83
2017-11-30 16:53


origen


Respuestas:


Se utiliza en las tablas de la pila de papel, que se puede ver, por ejemplo, en la salida del conjunto de mi respuesta a otra pregunta. Como se menciona en esa respuesta, su uso está definido por el Itanium C ++ ABI, donde se llama Rutina de Personalidad.

La razón por la que "funciona" definiéndolo como un puntero nulo mundial es probablemente porque nada arroja una excepción. Cuando algo trata de lanzar una excepción, entonces verá que se porta mal.

Por supuesto, si nada está usando excepciones, puede desactivarlas con -fno-exceptions (y si nada está usando RTTI, también puede agregar -fno-rtti) Si los está usando, tiene que (como otras respuestas ya indicadas) vincular con g++ en lugar de gcc, que agregará -lstdc++ para ti.


78
2017-11-30 19:00



Es parte del manejo de excepciones. El mecanismo gcc EH permite mezclar varios modelos EH, y se invoca una rutina de personalidad para determinar si coincide una excepción, qué finalización invocar, etc. Esta rutina de personalidad específica es para el manejo de excepciones C ++ (en oposición a, digamos, gcj / Java manejo de excepciones).


10
2017-11-30 17:27



El manejo de excepciones se incluye en implementaciones autónomas.

La razón de esto es que posiblemente uses gcc para compilar tu código Si compila con la opción -### notará que le falta la opción del enlazador -lstdc++ cuando invoca el proceso del enlazador. Compilando con g++ incluirá esa biblioteca y, por lo tanto, los símbolos definidos en ella.


9
2017-11-30 18:28



Un grep rápido de libstd++ base de código reveló los siguientes dos usos de __gx_personality_v0:

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

En 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: en realidad es un poco más complicado que eso, hay una compilación condicional que puede cambiar algunos detalles).

Por lo tanto, siempre que su código no esté usando el manejo de excepciones, defina el símbolo como void* no afectará nada, pero tan pronto como lo haga, se va a bloquear - __gxx_personality_v0 es una función, no un objeto global, por lo que intentar llamar a la función va a saltar a la dirección 0 y provocar una segfault.


5
2017-11-30 17:35



Tuve este error una vez y descubrí el origen:

Estaba usando un compilador gcc y mi archivo fue llamado CLIENT.C a pesar de que estaba haciendo un programa C y no un programa C ++.

gcc reconoce el .C extensión como programa C ++ y .c extensión como programa C (tenga cuidado con la C pequeña y la C grande).

Así que cambié el nombre de mi archivo CLIENT.c programa y funcionó.


5
2017-07-16 07:36



Las respuestas anteriores son correctas: se usa en el manejo de excepciones. los manual para GCC versión 6 tiene más información (que ya no está presente en el manual de la versión 7). El error puede surgir cuando se vincula una función externa que, desconocida para GCC, arroja excepciones Java.


1
2018-03-03 21:42