¿Para qué sirve __gxx_personality_v0?

4 minutos de lectura

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

Al compilar y vincular un programa C++ independiente mediante gcc, a veces se produce un error de vinculación 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 independiente. Solucionar el problema simplemente requiere definir este símbolo en alguna parte:

void *__gxx_personality_v0;

Lo cual está bien, pero no me gustan las cosas que funcionan mágicamente… Así que la pregunta es, ¿cuál es el propósito de este símbolo?

¿Para que sirve
cesarb

Se usa en las tablas de despliegue de pilas, que puede ver, por ejemplo, en el resultado del ensamblado de mi respuesta a otra pregunta. Como se menciona en esa respuesta, su uso está definido por el Itanium C++ ABIdonde se le llama Rutina de personalidad.

La razón por la que “funciona” al definirlo como un puntero nulo global NULL es probablemente porque nada está lanzando una excepción. Cuando algo intenta lanzar una excepción, verá que se comporta mal.

Por supuesto, si nada usa excepciones, puede deshabilitarlas con -fno-exceptions (y si nada está usando RTTI, también puede agregar -fno-rtti). Si los está utilizando, debe (como ya se señaló en otras respuestas) vincular con g++ en lugar de gccque agregará -lstdc++ para ti.

  • Gracias por el consejo sobre -fno-exceptions. yo añadí CPPFLAGS += -fno-exceptions a mi makefile, y eso resolvió el error.

    – Alan Kinnaman

    14/06/2016 a las 22:56

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 una excepción coincide, qué finalización invocar, etc. Esta rutina de personalidad específica es para el manejo de excepciones de C++ (a diferencia de, por ejemplo, gcj/Java manejo de excepciones).

¿Para que sirve
Johannes Schaub – litb

El manejo de excepciones está incluido en las implementaciones independientes.

La razón de esto es que posiblemente use gcc para compilar su código. Si compilas con la opción -### notará que 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.

  • Siempre pensé que compilar con g ++ solo era necesario cuando específicamente quería decirle al compilador que el código era C ++ (por ejemplo, extensión faltante). Ahora parece que al compilar el código C++ con gcc se pierde la inclusión de las bibliotecas come. Además de perder algunas bibliotecas, ¿hay otros “efectos secundarios” de compilar mi file.cpp con gcc en lugar de g++?

    – Lazer

    15 de mayo de 2010 a las 9:58


  • @eSkay hasta donde yo sé, la vinculación de libstdc++ es la única diferencia entre los dos.

    – Johannes Schaub – litb

    15 de mayo de 2010 a las 10:09

Un rápido grep de la libstd++ El código base 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).

Entonces, 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, te vas a estrellar – __gxx_personality_v0 es una función, no un objeto global, por lo que intentar llamar a la función saltará a la dirección 0 y provocará un error de segmento.

Tuve este error una vez y descubrí el origen:

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

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

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

1646758689 536 ¿Para que sirve
sagitta

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 al vincular una función externa que, desconocida para GCC, arroja excepciones de Java.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad