Для чего __gxx_personality_v0? - PullRequest
92 голосов
/ 30 ноября 2008

Это вопрос из вторых рук с сайта разработки ОС, но он меня заинтересовал, поскольку нигде не смог найти достойного объяснения.

При компиляции и компоновке автономной программы на C ++ с использованием gcc иногда возникает ошибка компоновщика, подобная этой:

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

Это очевидно потому, что этот символ определен в libstdc ++, который отсутствует в автономной среде. Решение проблемы просто требует определения где-нибудь этого символа:

void *__gxx_personality_v0;

Что приятно, но мне не нравятся вещи, которые просто волшебным образом работают ... Итак, вопрос в том, какова цель этого символа?

Ответы [ 6 ]

87 голосов
/ 30 ноября 2008

Используется в таблицах раскрутки стека, которые вы можете увидеть, например, в выводе сборки мой ответ на другой вопрос . Как уже упоминалось в этом ответе, его использование определяется Itanium C ++ ABI , где оно называется Индивидуальная процедура .

Причина, по которой он «работает», определяя его как глобальный пустой указатель NULL, возможно, в том, что ничто не вызывает исключение. Когда что-то пытается выбросить исключение, вы увидите, что оно плохо себя ведет.

Конечно, если ничто не использует исключения, вы можете отключить их с помощью -fno-exceptions (а если ничто не использует RTTI, вы также можете добавить -fno-rtti). Если вы используете их, вы должны (как уже отмечалось в других ответах) связать с g++ вместо gcc, что добавит -lstdc++ для вас.

10 голосов
/ 30 ноября 2008

Обработка исключений включена в автономные реализации.

Причина этого в том, что вы, возможно, используете gcc для компиляции своего кода. Если вы скомпилируете с параметром -###, вы заметите, что отсутствует параметр компоновщика -lstdc++, когда он вызывает процесс компоновщика. Компиляция с g++ будет включать эту библиотеку и, следовательно, символы, определенные в ней.

10 голосов
/ 30 ноября 2008

Это часть обработки исключений. Механизм gcc EH позволяет смешивать различные модели EH, и вызывается подпрограмма индивидуальности, чтобы определить, соответствует ли исключение, какую финализацию вызывать и т. Д. Эта специальная подпрограмма индивидуальности предназначена для обработки исключений в C ++ (в отличие, скажем, от gcj / Java). обработка исключений).

5 голосов
/ 16 июля 2014

Однажды у меня была эта ошибка, и я узнал источник:

Я использовал компилятор gcc, и мой файл назывался CLIENT.C, несмотря на то, что я делал программу на C, а не на C ++.

gcc распознает расширение .C как программу C ++, а расширение .c - как программу C (будьте осторожны с маленьким c и большим C).

Итак, я переименовал свою файловую CLIENT.c программу, и она сработала.

5 голосов
/ 30 ноября 2008

Быстрый поиск кода базы libstd++ показал следующие два использования __gx_personality_v0:

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

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

(Примечание: на самом деле все немного сложнее; есть условная компиляция, которая может изменить некоторые детали).

Таким образом, пока ваш код на самом деле не использует обработку исключений, определение символа как void* ни на что не повлияет, но как только это произойдет, вы потерпите крах - __gxx_personality_v0 - это функция, а не какой-то глобальный объект, поэтому попытка вызова функции приведет к переходу на адрес 0 и вызовет segfault.

2 голосов
/ 04 марта 2018

Ответы выше верны: он используется при обработке исключений. Руководство для GCC версии 6 содержит больше информации (которой больше нет в руководстве по версии 7). Ошибка может возникнуть при связывании внешней функции, которая - неизвестна GCC - выдает исключения Java.

...