Для чего нужен gxx personality v0?


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

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

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

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

7 84

7 ответов:

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

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

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

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

обработка исключений включена в свободно стоящие реализации.

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

быстрый grep из 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.

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

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

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

поэтому я переименовал свой файл и это сработало.

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

для тех, кто в основном пришел сюда, потому что увидели сообщение об ошибке, но не совсем понял все остальное, как мне. Это может быть не ваше решение, если вы действительно хотите сделать "автономную программу на C++".

что помогло мне решить все ошибки точки входа было поставить в " libstdc++-6.dll " из вашей папки компилятора, как MinGW рядом с вашим скомпилированным exe.

Это также решило проблемы с точкой входа от размещения строки std::.