Undefined ссылка на `__gxx_personality_sj0
С gcc 4.6 при попытке выполнить этот код:
#include <iostream>
using namespace std;
#include <bitset>
int main()
{
//Int<> a;
long long min = std::numeric_limits<int>::min();
unsigned long long max = std::numeric_limits<int>::max();
cout << "min: " << min << '\n';
cout << "max: " << max << '\n';
cout << (min <= max);
std::bitset<64> minimal(min);
cout << "minimal: " << minimal;
return 0;
}
Я получаю следующую ошибку:
1. undefined ссылка на __gxx_personality_sj0
2. undefined reference to
_Unwind_SjLj_Register '
3. undefined ссылка на _Unwind_SjLj_Unregister'
4. undefined reference to
_Unwind_SjLj_Resume '
Что, черт возьми, происходит?!
Ответы
Ответ 1
Эти функции являются частью поддержки обработки исключений С++ для GCC. GCC поддерживает два вида обработки исключений, один из которых основан на вызовах setjmp и longjmp (обработка исключений sjlj), а другой - на основе формата данных отладки DWARF (обработка исключений DW2).
Эти типы ошибок компоновщика будут возникать, если вы попытаетесь объединить объекты, которые были скомпилированы с различными реализациями обработки исключений в одном исполняемом файле. Похоже, что вы используете GCC DW2, но некоторая библиотека, которую вы пытаетесь использовать, была скомпилирована с помощью sjlj-версии GCC, что привело к этим ошибкам.
Короткий ответ заключается в том, что эти проблемы возникают из-за несовместимости ABI между различными компиляторами, и поэтому возникают, когда вы смешиваете библиотеки, скомпилированные с разными компиляторами, или используете несовместимые версии одного и того же компилятора.
Ответ 2
На всякий случай у кого-либо еще есть эта проблема: я изменил компиляторы ПОСЛЕ создания файлов .o
для моего проекта.
Когда я перестроил один и тот же проект, новый компилятор не создал новые .o
файлы, поэтому они не указали информацию о ключе. После удаления старых файлов и восстановления, ошибка была исправлена.
Я предполагаю, что восстановление с нуля, без удаления, будет работать одинаково.
Ответ 3
как smallB отметил в комментарии, возможно, вы использовали gcc
, ориентированный на программы C
, но у вас была программа C++
.
Чтобы скомпилировать программу C++
, обязательно используйте вместо этого драйвер компилятора g++
!
Пример:
BAD: gcc -o foo.exe foo.cpp
ХОРОШЕЕ: g++
-o foo.exe foo.cpp
Ответ 4
Команда gcc
- это просто программа-драйвер, которая запускает правильный компилятор для исходного файла, который вы ему даете (или запускайте компоновщик, если вы даете ему объектные файлы). Для исходного файла С++ с известным расширением файла он запустит компилятор С++ (который для GCC называется cc1plus
) и скомпилирует код правильно.
Но он не будет автоматически ссылаться на стандартную библиотеку С++ (которая для GCC называется libstdc++
).
Чтобы решить проблему, вам нужно либо явно связать эту библиотеку, добавив -lstdc++
к параметрам при компоновке, либо вместо этого просто скомпилировать и связать с ним драйвер g++
, который автоматически добавит -lstdc++
к компоновщику варианты.
Таким образом, вы можете использовать gcc
для компиляции программ на С++, но если вы используете какие-либо функции стандартной библиотеки или среды выполнения С++ (включая обработку исключений), вам необходимо связать с временем выполнения С++ с помощью -lstdc++
(или -lsupc++
только для времени выполнения). Использование g++
делает это автоматически.
Это описано в руководстве: https://gcc.gnu.org/onlinedocs/gcc/Invoking-G_002b_002b.html