To pytanie z drugiej ręki z witryny programistycznej systemu operacyjnego, ale zaciekawiło mnie, ponieważ nigdzie nie mogłem znaleźć przyzwoitego wyjaśnienia.
Podczas kompilowania i linkowania wolnostojącego programu w C ++ przy użyciu gcc, czasami pojawia się taki błąd konsolidatora:
out/kernel.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'
Jest to najwyraźniej spowodowane tym, że ten symbol jest zdefiniowany w libstdc ++, którego brakuje w wolnostojącym środowisku. Naprawienie problemu wymaga po prostu gdzieś zdefiniowania tego symbolu:
void *__gxx_personality_v0;
Co jest miłe, ale nie lubię rzeczy, które po prostu działają magicznie ... Więc pytanie brzmi, jaki jest cel tego symbolu?
-fno-exceptions
. DodałemCPPFLAGS += -fno-exceptions
do mojego pliku makefile i to rozwiązało błąd.To część obsługi wyjątków. Mechanizm gcc EH pozwala mieszać różne modele EH, a procedura osobowości jest wywoływana w celu określenia, czy wyjątek pasuje, jaką finalizację wywołać itp. Ta specyficzna procedura osobowości służy do obsługi wyjątków w C ++ (w przeciwieństwie do, powiedzmy, gcj / Java Obsługa wyjątków).
źródło
Obsługa wyjątków jest zawarta w wolnostojących implementacjach.
Powodem tego jest to, że prawdopodobnie używasz
gcc
do kompilacji kodu. Jeśli kompilujesz z opcją-###
, zauważysz, że brakuje opcji konsolidatora,-lstdc++
gdy wywołuje ona proces konsolidatora. Kompilowanie zg++
będzie zawierało tę bibliotekę, a tym samym symbole w niej zdefiniowane.źródło
file.cpp
pomocągcc
zamiastg++
?libstdc++
jedyną różnicą między nimi jest linkowanie .Szybkie przeglądanie
libstd++
bazy kodu ujawniło następujące dwa zastosowania__gx_personality_v0
:W libsupc ++ / relax-cxx.h
W libsupc ++ / eh_personality.cc
(Uwaga: w rzeczywistości jest to trochę bardziej skomplikowane; istnieje pewna kompilacja warunkowa, która może zmienić niektóre szczegóły).
Tak więc, o ile twój kod nie korzysta z obsługi wyjątków, zdefiniowanie symbolu jako
void*
nie wpłynie na nic, ale gdy tylko to zrobi, nastąpi awaria -__gxx_personality_v0
to funkcja, a nie jakiś obiekt globalny, więc spróbuj wywołanie funkcji powoduje przejście do adresu 0 i spowodowanie segfault.źródło
Miałem raz ten błąd i znalazłem pochodzenie:
Używałem kompilatora GCC i mój plik został wywołany,
CLIENT.C
mimo że robiłem program w C, a nie w C ++.gcc rozpoznaje
.C
rozszerzenie jako program C ++, a.c
rozszerzenie jako program C (uważaj na małe c i duże C).Więc zmieniłem nazwę mojego
CLIENT.c
programu plików i zadziałało.źródło
Powyższe odpowiedzi są poprawne: jest używany w obsłudze wyjątków. Instrukcja dla GCC w wersji 6 ma więcej informacji (który nie jest już obecny jest w wersji 7 instrukcji). Błąd może wystąpić podczas łączenia funkcji zewnętrznej, która - nieznana GCC - zgłasza wyjątki Java.
źródło