web-dev-qa-db-fra.com

A quoi sert __gxx_personality_v0?

C'est une question de seconde main posée sur un site de développement de système d'exploitation, mais cela m'a rendu curieux, car je ne pouvais trouver d'explication décente nulle part.

Lors de la compilation et de la liaison d'un programme C++ autonome à l'aide de gcc, une erreur telle que celle-ci se produit parfois:

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

Ceci est apparemment dû au fait que ce symbole est défini dans libstdc ++, qui fait défaut dans un environnement autonome. Résoudre le problème nécessite simplement de définir ce symbole quelque part:

void *__gxx_personality_v0;

Qui est Nice, mais je n'aime pas les choses qui fonctionnent comme par magie ... La question est donc de savoir quel est le but de ce symbole.

93
Bruce Johnston

Il est utilisé dans les tables de pile de la pile, que vous pouvez voir par exemple dans la sortie Assembly de ma réponse à une autre question . Comme mentionné dans cette réponse, son utilisation est définie par le Itanium C++ ABI , où il est appelé le Personality Routine .

La raison pour laquelle il "fonctionne" en le définissant comme un pointeur NULL void global est probablement parce que rien ne lève d'exception. Quand quelque chose essaie de lancer une exception, alors vous verrez qu'elle se comporte mal.

Bien sûr, si rien n’utilise d’exceptions, vous pouvez les désactiver avec -fno-exceptions (et si rien n’utilise RTTI, vous pouvez aussi ajouter -fno-rtti). Si vous les utilisez, vous devez (comme d’autres réponses déjà notées) créer un lien avec g++ _ au lieu de gcc, ce qui ajoutera -lstdc++ pour toi.

87
CesarB

Cela fait partie de la gestion des exceptions. Le mécanisme gcc EH permet de mélanger différents modèles EH. Une routine de personnalité est appelée pour déterminer si une exception correspond, quelle finalisation utiliser, etc. Cette routine de personnalité spécifique est destinée à la gestion des exceptions C++ (par exemple, gcj/Java gestion des exceptions).

11
Martin v. Löwis

La gestion des exceptions est incluse dans les implémentations autonomes.

La raison en est que vous pouvez éventuellement utiliser gcc pour compiler votre code. Si vous compilez avec l'option -### vous remarquerez qu'il manque l'option de l'éditeur de liens -lstdc++ quand il appelle le processus de l'éditeur de liens. Compiler avec g++ inclura cette bibliothèque et donc les symboles qui y sont définis.

11

Un rapide grep du libstd++ code base a révélé les deux utilisations suivantes de __gx_personality_v0:

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

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

(Remarque: c'est en fait un peu plus compliqué que cela; il y a une compilation conditionnelle qui peut changer certains détails).

Donc, tant que votre code n'utilise pas réellement la gestion des exceptions, définissez le symbole comme void* n'affectera rien, mais dès que cela se produira, vous allez planter - __gxx_personality_v0 est une fonction, pas un objet global, donc essayer d’appeler la fonction va sauter à l’adresse 0 et provoquer une erreur de segmentation.

6
Adam Rosenfield

J'ai eu cette erreur une fois et j'ai découvert l'origine:

J'utilisais un compilateur gcc et mon fichier s'appelait CLIENT.C malgré que je faisais un programme C et non un programme C++.

gcc reconnaît le .C extension en tant que programme C++ et .c extension en tant que programme C (faites attention au petit c et au grand C).

J'ai donc renommé mon fichier CLIENT.c programme et cela a fonctionné.

6
jlguenego

Les réponses ci-dessus sont correctes: il est utilisé dans la gestion des exceptions. Le manuel pour GCC version 6 contient plus d'informations (qui n'est plus présent dans le manuel de la version 7). L'erreur peut survenir lors de la liaison d'une fonction externe qui - inconnue de GCC - génère des exceptions Java.

2
sagitta