Для чего __gxx_personality_v0?
Это вопрос из вторых рук с сайта разработки ОС, но мне было любопытно, потому что я не мог найти достойного объяснения где угодно.
При компиляции и связывании отдельно стоящей программы на С++ с использованием gcc иногда возникает такая ошибка компоновщика:
out/kernel.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'
Это, по-видимому, потому, что этот символ определен в libstdС++, который отсутствует в свободностоящей среде. Исправление проблемы просто требует определения этого символа где-то:
void *__gxx_personality_v0;
Это хорошо, но мне не нравятся вещи, которые просто магически работают... Итак, вопрос в том, какова цель этого символа?
Ответы
Ответ 1
Он используется в неперекрывающихся таблицах, которые вы можете увидеть, например, в сборке моего ответа на другой вопрос. Как упоминалось в этом ответе, его использование определяется Itanium С++ ABI, где оно называется "Личность" .
Причина, по которой он "работает", определяя его как глобальный указатель void NULL, вероятно, потому, что ничего не выбрасывает исключение. Когда что-то пытается выбросить исключение, вы увидите, что оно ошибочно.
Конечно, если ничего не использует исключения, вы можете отключить их с помощью -fno-exceptions
(и если ничего не используется RTTI, вы также можете добавить -fno-rtti
). Если вы используете их, вы должны (как уже отмечалось, другие ответы) ссылаться на g++
вместо gcc
, что добавит -lstdc++
для вас.
Ответ 2
Это часть обработки исключений. Механизм gcc EH позволяет смешивать различные модели EH, и вызывается индивидуальная процедура, чтобы определить, соответствует ли совпадение, какую завершающую процедуру вызывать и т.д. Эта специфическая рутина для обработки исключений С++ (в отличие от, скажем, gcj/Java обработка исключений).
Ответ 3
Обработка исключений включена в свободностоящие реализации.
Причина этого заключается в том, что вы можете использовать gcc
для компиляции кода. Если вы скомпилируете с опцией -###
, вы заметите, что отсутствует компоновщик -lstdc++
, когда он вызывает процесс компоновщика. Компиляция с помощью g++
будет включать эту библиотеку и, следовательно, символы, определенные в ней.
Ответ 4
Быстрый grep базы кода libstd++
показал следующие два использования __gx_personality_v0
:
В libsupС++/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 *);
В libsupС++/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.
Ответ 5
У меня была эта ошибка один раз, и я узнал происхождение:
Я использовал компилятор gcc, и мой файл был вызван CLIENT.C
, несмотря на то, что я выполнял программу на C, а не программу на С++.
gcc распознает расширение .C
как программу С++ и расширение .C
как программу C (будьте осторожны с маленькими c и большими C).
Итак, я переименовал мою программу CLIENT.C
и работал.
Ответ 6
Ответы правильны: он используется в обработке исключений. руководство для GCC версии 6 содержит дополнительную информацию (которая больше не присутствует в руководстве по версии 7). Ошибка может возникнуть при связывании внешней функции, которая - неизвестна для GCC - выбрасывает исключения Java.