При попытке сборки программы появляется сообщение об ошибке одного из следующих видов:
ссылка на неразрешенный внешний символ ...
unresolved external symbol ...
undefined reference to ...
Что это значит, и как исправить такую ошибку?
Ответ
Определение:
Данная ошибка означает, что в процессе компоновки программы, компоновщик не смог найти определение некоторой сущности, на которую есть ссылка (попытка использования) в программе.
К таким сущностям может относиться, например, функция или переменная.
Причины и решения:
Возможных причин появления ошибки может быть несколько и это зависит от того, что представляет из себя собираемый проект. Всё множество ситуаций можно разбить на две большие группы:
Используются сторонние библиотеки
Не указана необходимая (статическая) библиотека для компоновщика.
Например, к проекту подключен только *.h файл с объявлениями, но отсутствует код реализации, обычно это *.lib или *.a файлы (в зависимости от используемой системы).
Требуется явно подключить библиотеку к проекту. Для Visual C++ это можно сделать добавлением следующей строки прямо в код:
#pragma comment(lib, "libname.lib")
Для gcc/clang требуется указать файл через ключ -l (эль)
Для Qt в .pro файле нужно использовать переменную LIBS
LIBS += -L[путь_к_библиотеке] -l[имя_библиотеки]
Для системы сборки cmake есть target_link_libraries
Библиотека указана, но не совпадает разрядность библиотеки и компилируемого кода.
В общем случае, разрядность собираемого проекта (приложения или библиотеки) должна совпадать с разрядностью используемой сторонней библиотеки. Обычно производители библиотек предоставляют возможность выбора 32 или 64 бит версию использовать. Если библиотека поставляется в исходных кодах и собирается отдельно от текущего проекта, нужно также выбрать правильную разрядность.
Библиотека указана, но она собрана для другой (не совместимой) ОС.
Например при сборке проекта в Windows осуществляется попытка использовать бинарный файл, собранный для Linux. В данном случае нужно использовать файлы, подходящие для вашей ОС.
Библиотека указана, но она собрана другим компилятором, не совместимым с используемым.
Объектные файлы, полученные путем сборки C++ кода разными компиляторами для одной и той же ОС могут быть бинарно несовместимы друг с другом. Требуется использовать совместимые (скорее всего и вовсе одинаковые) компиляторы.
Библиотека указана, и собрана тем же компилятором, что и основной проект, но используются разные версии Run-Time библиотек.
Например, для Visual C++ возможна ситуация, когда библиотека собрана с ключом /MDd, а основной проект с /MTd. Требуется задать ключи так, чтобы использовались одинаковые версии Run-Time библиотек.
Сторонние библиотеки не используются
Просто отсутствует определение функции.
void f(int); // всего лишь объявление. Нет `тела` функции
int main(){
f(42); // undefined reference to `f(int)'
}
Требуется добавить определение функции f
void f(int) {
// тело функции
}
Отсутствует определение статической переменной класса.
struct S {
static int i;
};
int main() {
S s;
s.i = 42; // undefined reference to `S::i'
}
Нужно добавить определение (выделить память) переменной:
int S::i;
Неправильная реализация шаблонного кода.
Например, реализация шаблонного кода помещена в *.cpp файл, хотя она должна находиться полностью в подключаемом *.h файле.
Файл с кодом не был скомпилирован.
Например, в случае использования make-файла не было прописано правило построения файла, а в случае использования IDE типа Visual Studio *.cpp файл не добавлен в список файлов проекта.
Виртуальная функция в базовом классе не объявлена как =0 (pure-virtual).
struct B {
void virtual f();
};
struct D : B {
void f() {}
};
int main() {
D d;
}
При использовании иерархии классов функция в базовом классе, не имеющая реализации должна быть помечена как "чистая":
struct B {
void virtual f() = 0;
};
Имя не имеет внешнего связывания.
Например, есть объявление функции f в модуле А и даже ее реализация в модуле B, но реализация помечена как static
// A.cpp
void f();
int main() {
f(); // undefined reference to `f()'
}
// B.cpp
static void f() {}
Аналогичная ситуация может возникнуть при использовании безымянного пространства имен:
// B.cpp
namespace {
void f() {}
}
Комментариев нет:
Отправить комментарий