Pour quoi __gxx_personality_v0 est-il?

Ceci est une question de seconde main sur un site de développement de système d’exploitation, mais cela m’a rendu curieux car je n’ai trouvé aucune explication décente nulle part.

Lors de la compilation et de la liaison d’un programme C ++ autonome à l’aide de gcc, une erreur de l’éditeur de liens comme celle-ci se produit parfois:

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

C’est apparemment parce que ce symbole est défini dans libstdc ++, qui manque dans un environnement autonome. Corriger le problème nécessite simplement de définir ce symbole quelque part:

 void *__gxx_personality_v0; 

Ce qui est bien, mais je n’aime pas les choses qui fonctionnent comme par magie … Alors, la question est: quel est le but de ce symbole?

Il est utilisé dans les tables de défilement de la stack, que vous pouvez voir par exemple dans la sortie d’assemblage de ma réponse à une autre question . Comme mentionné dans cette réponse, son utilisation est définie par l’ IBI Itanium C ++ , appelée routine de personnalité .

La raison pour laquelle il “fonctionne” en le définissant comme un pointeur vide NULL global est probablement que rien ne lance une exception. Lorsque quelque chose essaie de lancer une exception, alors vous le verrez mal se comporter.

Bien sûr, si rien n’utilise des exceptions, vous pouvez les désactiver avec -fno-exceptions (et si rien n’utilise RTTI, vous pouvez également append -fno-rtti ). Si vous les utilisez, vous devez (comme d’autres réponses l’ont déjà fait remarquer) établir un lien avec g++ au lieu de gcc , qui appenda -lstdc++ pour vous.

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

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

La raison en est que vous utilisez éventuellement gcc pour comstackr votre code. Si vous comstackz avec l’option -### vous remarquerez qu’il manque l’option linker -lstdc++ lorsqu’il appelle le processus de l’éditeur de liens. Comstackr avec g++ inclura cette bibliothèque, et donc les symboles qui y sont définis.

Un rapide grep de la base de code libstd++ 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 ... } 

(Note: en fait, c’est un peu plus compliqué que ça; il y a une compilation conditionnelle qui peut changer certains détails).

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

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é un programme C et non un programme C ++.

gcc reconnaît l’extension .C tant que programme C ++ et l’extension .C tant que programme C (attention aux petits c et big C).

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

Les réponses ci-dessus sont correctes: elles sont utilisées dans la gestion des exceptions. Le manuel de la version 6 de GCC contient plus d’informations (qui ne figurent plus dans le manuel de la version 7). L’erreur peut survenir lors de la liaison d’une fonction externe qui, inconnue de GCC, émet des exceptions Java.