it-swarm.com.de

Wofür ist __gxx_personality_v0?

Dies ist eine Frage aus zweiter Hand von einer OS-Entwicklungssite, aber sie hat mich neugierig gemacht, da ich nirgendwo eine anständige Erklärung finden konnte.

Beim Kompilieren und Verknüpfen eines eigenständigen C++ - Programms mit gcc tritt manchmal der folgende Linker-Fehler auf:

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

Dies liegt anscheinend daran, dass dieses Symbol in libstdc ++ definiert ist, das in einer freistehenden Umgebung fehlt. Um das Problem zu beheben, müssen Sie lediglich dieses Symbol definieren:

void *__gxx_personality_v0;

Was ist Nizza, aber ich mag keine Dinge, die auf magische Weise funktionieren ... Die Frage ist also, was ist der Zweck dieses Symbols?

93
Bruce Johnston

Es wird in den Stapel-Auflösetabellen verwendet, die Sie zum Beispiel in der Assembly-Ausgabe von meine Antwort auf eine andere Frage sehen können. Wie in dieser Antwort erwähnt, wird ihre Verwendung durch Itanium C++ ABI definiert, wobei sie Personality Routine genannt wird.

Der Grund, warum es "funktioniert", indem es als globaler Null-Leerzeiger definiert wird, ist wahrscheinlich, dass nichts eine Ausnahme auslöst. Wenn etwas versucht, eine Ausnahme auszulösen, werden Sie feststellen, dass es sich schlecht benimmt.

Wenn keine Ausnahmen verwendet werden, können Sie diese natürlich mit -fno-exceptions Deaktivieren (und wenn RTTI nicht verwendet wird, können Sie auch -fno-rtti Hinzufügen). Wenn Sie sie verwenden, müssen Sie (wie andere bereits erwähnte Antworten) mit g++ Anstelle von gcc verknüpfen, wodurch -lstdc++ Für Sie hinzugefügt wird.

87
CesarB

Dies ist Teil der Ausnahmebehandlung. Der gcc-EH-Mechanismus ermöglicht das Mischen verschiedener EH-Modelle, und eine Persönlichkeitsroutine wird aufgerufen, um zu bestimmen, ob eine Ausnahme zutrifft, welche Finalisierung aufzurufen ist usw. Diese spezifische Persönlichkeitsroutine ist für die C++ - Ausnahmebehandlung vorgesehen (im Gegensatz zu beispielsweise gcj/Java Ausnahmebehandlung).

11

Die Ausnahmebehandlung ist in freistehenden Implementierungen enthalten.

Der Grund dafür ist, dass Sie möglicherweise gcc verwenden, um Ihren Code zu kompilieren. Wenn Sie mit der Option -### Kompilieren, werden Sie feststellen, dass die Linker-Option -lstdc++ Fehlt, wenn der Linker-Prozess aufgerufen wird. Das Kompilieren mit g++ Schließt diese Bibliothek und damit die darin definierten Symbole ein.

Ein kurzer Blick auf das libstd++ Codebasis ergab die folgenden zwei Verwendungen von __gx_personality_v0:

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

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

(Hinweis: Es ist tatsächlich etwas komplizierter. Es gibt eine bedingte Kompilierung, die einige Details ändern kann.).

Solange Ihr Code keine Ausnahmebehandlung verwendet, definieren Sie das Symbol als void* wird nichts beeinflussen, aber sobald es passiert, wirst du abstürzen - __gxx_personality_v0 ist eine Funktion, kein globales Objekt. Wenn Sie also versuchen, die Funktion aufzurufen, springen Sie zur Adresse 0 und verursachen einen Segfault.

6
Adam Rosenfield

Ich hatte diesen Fehler einmal und fand den Ursprung heraus:

Ich habe einen gcc-Compiler verwendet und meine Datei wurde CLIENT.C Genannt, obwohl ich ein C-Programm und kein C++ - Programm ausgeführt habe.

gcc erkennt die Erweiterung .C als C++ - Programm und die Erweiterung .c als C-Programm (achten Sie auf das kleine C und das große C).

Also habe ich meine Datei CLIENT.c Umbenannt und es hat funktioniert.

6
jlguenego

Die obigen Antworten sind korrekt: Sie werden für die Ausnahmebehandlung verwendet. Das Handbuch für GCC Version 6 enthält weitere Informationen (die im Handbuch der Version 7 nicht mehr enthalten sind). Der Fehler kann beim Verknüpfen einer externen Funktion auftreten, die - GCC nicht bekannt - Java Ausnahmen auslöst.

2
sagitta