Ошибка средств компоновщика LNK2019 | Microsoft Docs

Все сведения об ошибке компоновщика Microsoft Visual Studio LNK2019 и об их диагностике и исправлении в коде C и C++.

Определение

Данная ошибка означает, что в процессе компоновки программы, компоновщик не смог найти определение некоторой сущности, на которую есть ссылка (попытка использования) в программе.

К таким сущностям может относиться, например, функция или переменная.

Возможные причиныPossible causes

Существует множество способов получения этой ошибки.There are many ways to get this error. Все они используют ссылку на функцию или переменную, которую компоновщику не удалось Разрешить, или найти определение для.All of them involve a reference to a function or variable that the linker couldn’t resolve, or find a definition for. Компилятор может определить, когда символ не объявлен, но не может определить, не определенли символ.The compiler can identify when a symbol isn’t declared, but it can’t tell when the symbol isn’t defined. Это связано с тем, что определение может находиться в другом исходном файле или библиотеке.That’s because the definition may be in a different source file or library. Если символ упоминается, но не определен, компоновщик создает неразрешенную extern ошибку символа Al.If a symbol is referred to but never defined, the linker generates an unresolved external symbol error.

Ниже приведены некоторые распространенные проблемы, вызывающие ошибку LNK2019.Here are some common problems that cause LNK2019:

Исходный файл, содержащий определение символа, не скомпилированThe source file that contains the definition of the symbol isn’t compiled

В Visual Studio убедитесь, что исходный файл, определяющий символ, компилируется как часть проекта.In Visual Studio, make sure the source file that defines the symbol gets compiled as part of your project. Проверьте промежуточный каталог выходных данных сборки на наличие соответствующего OBJ-файла.Check the intermediate build output directory for a matching .obj file. Если исходный файл не компилируется, щелкните его правой кнопкой мыши в обозреватель решений и выберите пункт Свойства , чтобы проверить свойства файла.If the source file isn’t compiled, right-click on the file in Solution Explorer and choose Properties to check the properties of the file. На странице Свойства конфигурации > Общие должен отображаться тип элемента компилятора C/C++.The Configuration Properties > General page should show an Item Type of C/C++ Compiler. В командной строке убедитесь, что исходный файл, содержащий определение, скомпилирован.On the command line, make sure the source file that contains the definition is compiled.

Объектный файл или библиотека, содержащие определение символа, не связаныThe object file or library that contains the definition of the symbol isn’t linked

Убедитесь, что в Visual Studio объектный файл или библиотека, содержащие определение символа, связаны как часть проекта.In Visual Studio, make sure the object file or library that contains the symbol definition is linked as part of your project. В командной строке убедитесь, что список файлов для связывания содержит объектный файл или библиотеку.On the command line, make sure the list of files to link includes the object file or library.

Объявление символа написано не так, как определение символаThe declaration of the symbol isn’t spelled the same as the definition of the symbol

Проверьте правильность написания и регистра символов в объявлении и определении, а также в любом месте, где используется или вызывается символ.Verify you use the correct spelling and capitalization in both the declaration and the definition, and wherever the symbol is used or called.

Используется функция, но тип или число параметров не соответствуют определению функцииA function is used but the type or number of the parameters don’t match the function definition

Объявление функции должно соответствовать определению.The function declaration must match the definition. Убедитесь, что вызов функции соответствует объявлению и что объявление соответствует определению.Make sure the function call matches the declaration, and that the declaration matches the definition. Код, который вызывает функции шаблона, также должен иметь совпадающие объявления функции шаблона, включающие те же параметры шаблона, что и определение.Code that invokes template functions must also have matching template function declarations that include the same template parameters as the definition. Пример несоответствия объявления шаблона см. в разделе Sample LNK2019e. cpp статьи “примеры”.For an example of a template declaration mismatch, see sample LNK2019e.cpp in the Examples section.

Функция или переменная объявлена, но не определенаA function or variable is declared but not defined

Ошибка LNK2019 может возникать, если объявление существует в файле заголовка, но соответствующее определение не реализовано.LNK2019 can occur when a declaration exists in a header file, but no matching definition is implemented. Для функций элементов или static элементов данных реализация должна включать селектор области класса.For member functions or static data members, the implementation must include the class scope selector. Пример см. в разделе Missing Function Body or Variable.For an example, see Missing Function Body or Variable.

Соглашение о вызовах отличается между объявлением функции и определением функции.The calling convention is different between the function declaration and the function definition

Соглашения о вызовах ( __cdecl , __stdcall , __fastcall или __vectorcall ) кодируются как часть декорированного имени.Calling conventions (__cdecl, __stdcall, __fastcall, or __vectorcall) are encoded as part of the decorated name. Убедитесь, что соглашение о вызовах одинаково.Make sure the calling convention is the same.

Символ определен в файле C, но объявлен без использования extern “C” в файле C++A symbol is defined in a C file, but declared without using extern “C” in a C++ file

Символы, определенные в файле, который компилируется как C, имеют разные декорированные имена, чем символы, объявленные в файле C++, если не используется модификатор extern “C” .Symbols defined in a file that is compiled as C have different decorated names than symbols declared in a C++ file unless you use an extern “C” modifier. Убедитесь, что объявление соответствует компоновке компиляции для каждого символа.Make sure the declaration matches the compilation linkage for each symbol. Аналогично, если символ определяется в файле C++, который будет использоваться программой C, в определении следует использовать extern “C” .Similarly, if you define a symbol in a C++ file that will be used by a C program, use extern “C” in the definition.

Символ определяется как static , а затем на него указывает ссылка за пределами файлаA symbol is defined as static and then later referenced outside the file

В C++, в отличие от C, Глобальная const Ants имеет static компоновку.In C++, unlike C, global constants have static linkage. Чтобы обойти это ограничение, можно включить const инициализацию в файл заголовка и включить этот заголовок в cpp-файлы. Кроме того, можно сделать переменную const Ant и использовать const ссылку Ant для доступа к ней.To get around this limitation, you can include the const initializations in a header file and include that header in your .cpp files, or you can make the variable non-constant and use a constant reference to access it.

staticЧлен класса не определенA static member of a class isn’t defined

staticЧлен класса должен иметь уникальное определение или будет нарушать правило одного определения.A static class member must have a unique definition, or it will violate the one-definition rule. staticЧлен класса, который не может быть определен как встроенный, должен быть определен в одном исходном файле с помощью его полного имени.A static class member that can’t be defined inline must be defined in one source file by using its fully qualified name. Если он не определен вообще, компоновщик создает ошибку LNK2019.If it isn’t defined at all, the linker generates LNK2019.

Зависимость сборки определяется только в качестве зависимости проекта в решенииA build dependency is only defined as a project dependency in the solution

В более ранних версиях Visual Studio было достаточно этого уровня зависимостей.In earlier versions of Visual Studio, this level of dependency was sufficient. Однако начиная с Visual Studio 2010 для Visual Studio требуется ссылка междупроектами.However, starting with Visual Studio 2010, Visual Studio requires a project-to-project reference. Если в проекте нет ссылки проекта на проект, может возникнуть Эта ошибка компоновщика.If your project doesn’t have a project-to-project reference, you may receive this linker error. Чтобы устранить ошибку, добавьте ссылку одного проекта на другой.Add a project-to-project reference to fix it.

Точка входа не определенаAn entry point isn’t defined

Код приложения должен определять соответствующую точку входа: main или wmain для консольных приложений, WinMain или wWinMain для приложений Windows.The application code must define an appropriate entry point: main or wmain for console applications, and WinMain or wWinMain for Windows applications. Дополнительные сведения см. в разделе main функция и аргументы командной строки или WinMain функция.For more information, see main function and command-line arguments or WinMain function. Чтобы использовать настраиваемую точку входа, укажите параметр компоновщика /Entry (символ точки входа) .To use a custom entry point, specify the /ENTRY (Entry-Point Symbol) linker option.

Построение консольного приложения с помощью параметров для приложения WindowsYou build a console application by using settings for a Windows application

Если сообщение об ошибке похоже на неразрешенный extern символ Al, WinMain указанный в функции function_name, СВЯЖИТЕ с помощью параметра /SUBSYSTEM: Console вместо /SUBSYSTEM: Windows.If the error message is similar to unresolved external symbol WinMain referenced in function function_name, link by using /SUBSYSTEM:CONSOLE instead of /SUBSYSTEM:WINDOWS. Дополнительные сведения об этом параметре и инструкции о том, как задать это свойство в Visual Studio, см. в статье /SUBSYSTEM (Specify Subsystem).For more information about this setting, and for instructions on how to set this property in Visual Studio, see /SUBSYSTEM (Specify Subsystem).

Вы пытаетесь связать 64-разрядные библиотеки с 32-битным кодом или 32-bit Library в 64-разрядный код.You attempt to link 64-bit libraries to 32-bit code, or 32-bit libraries to 64-bit code

Библиотеки и объектные файлы, связанные с вашим кодом, должны быть скомпилированы для той же архитектуры, что и код.Libraries and object files linked to your code must be compiled for the same architecture as your code. Убедитесь, что библиотеки, на которые ссылается проект, компилируются для той же архитектуры, что и проект.Make sure the libraries your project references are compiled for the same architecture as your project. Убедитесь, что свойство /libpath или Дополнительные каталоги библиотек указывает на библиотеки, созданные для правильной архитектуры.Make sure the /LIBPATH or Additional Library Directories property points to libraries built for the correct architecture.

Для встраивания функций в разные исходные файлы используются различные параметры компилятораYou use different compiler options for function inlining in different source files

Использование встроенных функций, определенных в CPP-файлах, и смешение в различных исходных файлах параметров компилятора для встраивания функций может привести к возникновению ошибки LNK2019.Using inlined functions defined in .cpp files and mixing function inlining compiler options in different source files can cause LNK2019. Для получения дополнительной информации см. Function Inlining Problems.For more information, see Function Inlining Problems.

Автоматические переменные используются вне области действияYou use automatic variables outside their scope

Автоматические переменные (области видимости функции) могут использоваться только в области видимости данной функции.Automatic (function scope) variables can only be used in the scope of that function. Эти переменные нельзя объявлять extern и использовать в других исходных файлах.These variables can’t be declared extern and used in other source files. Пример см. в разделе Automatic (Function Scope) Variables.For an example, see Automatic (Function Scope) Variables.

Вы вызываете встроенные функции или передайте типы аргументов в встроенные функции, которые не поддерживаются в целевой архитектуре.You call intrinsic functions or pass argument types to intrinsic functions that aren’t supported on your target architecture

Например, если вы используете AVX2 встроенную функцию, но не указываете параметр компилятора / ARCH : AVX2 , компилятор предполагает, что встроенная функция является extern функцией Al.For example, if you use an AVX2 intrinsic, but don’t specify the /ARCH:AVX2 compiler option, the compiler assumes that the intrinsic is an external function. Вместо создания встроенной инструкции компилятор создает вызов extern символа Al с тем же именем, что и встроенная инструкция.Instead of generating an inline instruction, the compiler generates a call to an external symbol with the same name as the intrinsic. Когда компоновщик пытается найти определение этой отсутствующей функции, он создает ошибку LNK2019.When the linker tries to find the definition of this missing function, it generates LNK2019. Убедитесь, что используются только встроенные функции и типы, поддерживаемые целевой архитектурой.Make sure you only use intrinsics and types supported by your target architecture.

Вы занимаетесь смешением кода, который использует собственный wchar_t код с кодом, который неYou mix code that uses native wchar_t with code that doesn’t

Действия по согласованности языка C++, выполненные в Visual Studio 2005, сделали wchar_t собственный тип по умолчанию.C++ language conformance work that was done in Visual Studio 2005 made wchar_t a native type by default. Если не все файлы были скомпилированы с использованием одних и тех же параметров **/Zc: wchar_t ** , ссылки типа могут не разрешаться в совместимые типы.If not all files have been compiled by using the same /Zc:wchar_t settings, type references may not resolve to compatible types. Убедитесь wchar_t , что типы во всех файлах библиотек и объектов совместимы.Make sure wchar_t types in all library and object files are compatible. Либо обновите из wchar_t определения типа, либо используйте соответствующие параметры **/Zc: wchar_t ** при компиляции.Either update from a wchar_t typedef, or use consistent /Zc:wchar_t settings when you compile.

Решение

Я получил двоичные файлы от http://glew.sourceforge.net/index.html (https://sourceforge.net/projects/glew/files/glew/1.9.0/glew-1.9.0-win32.zip/download)
и FreeGLUT 2.8.0 MSVC Пакет от http://www.transmissionzero.co.uk/software/freeglut-devel/ (http://files.transmissionzero.co.uk/software/development/GLUT/freeglut-MSVC.zip)

Я установил путь включения glew-1.9.0include, freeglutinclude и путь к библиотеке freeglutlib, glew-1.9.0lib,

Я исправил заголовок вашего файла как

#include <Windows.h>#include <iostream>#include <gl/glew.h>#include <gl/GL.h>#include <gl/freeglut.h>#pragma comment(lib, “glew32.lib”)

Ссылка удалась, и это сработало.

UPD

При использовании сторонних библиотек, как правило:

  • Вы должны установить путь включения <3rdPartyDir>include, но не для <3rdPartyDir>includelib_name, Объявить о его включении в исходный код следует:

правильный: #include <lib_name/header_name.h>

неправильно: #include <header_name.h>потому что внутри библиотеки могут быть внутренние зависимости, например #include <lib_name/other_header_name.h>

  • Установите путь к библиотеке <3rdPartyDir>lib, Затем необходимо указать необходимые библиотеки одним из следующих способов:

Для MSVC добавьте

#ifdef _MSC_VER#pragma comment(lib, “lib1_name.lib”)#pragma comment(lib, “lib2_name.lib”)/// etc#endif

Или добавьте необходимые библиотеки в опции компоновщика.

Некоторые библиотеки поддерживают механизм автоматической компоновки (например, freeglut), то есть заголовочный файл содержит строку типа #pragma comment(lib, “lib1_name.lib”)

  • Скопируйте необходимые библиотеки из <3rdPartyDir>bin в <MyExePath>

6

Ваша связь потребляет библиотеки, перед тем как объектные файлы, которые относятся к ним

  • Вы пытаетесь компилировать и компоновать свою программу с помощью набора инструментов GCC.
  • Ваша связь указывает все необходимые библиотеки и поиск путей к библиотеке
  • Если libfoo зависит от libbar, то ваша связь правильно ставит libfoo ” до ” libbar.
  • Ваша связь не с неопределенная ссылка на что-то ошибки.
  • Но все-неопределенные что-тоы объявляются в заголовочных файлах у вас`#включить бы и в самом деле, определенные в библиотеках, которые вы соединяете.Примеры на C. Они могли одинаково хорошо быть c++

    Минимальный пример с участием статической Библиотеке вы построили себе

    my_lib.с

    #include “my_lib.h”#include <stdio.h>void hw(void){ puts(“Hello World”);}

my_lib.ч

#ifndef MY_LIB_H#define MT_LIB_Hextern void hw(void);#endif

eg1.с

#include <my_lib.h>int main(){ hw(); return 0;}

Вы строите свою статическую библиотеку:

$ gcc -c -o my_lib.o my_lib.c$ ar rcs libmy_lib.a my_lib.o

Вы компилируете вашу программу:

$ gcc -I. -c -o eg1.o eg1.c

Вы пытаетесь связать его с libmy_lib.и не:

$ gcc -o eg1 -L. -lmy_lib eg1.o eg1.o: In function `main’:eg1.c:(.text+0x5): undefined reference to `hw’collect2: error: ld returned 1 exit status

Тот же результат, если вы скомпилировать и скомпоновать в одном шаге, как:

$ gcc -o eg1 -I. -L. -lmy_lib eg1.c/tmp/ccQk1tvs.o: In function `main’:eg1.c:(.text+0x5): undefined reference to `hw’collect2: error: ld returned 1 exit status

Минимальный пример с участием в общей библиотечной системы, библиотеки сжатия сайт libz

eg2.с

#include <zlib.h>#include <stdio.h>int main(){ printf(“%sn”,zlibVersion()); return 0;}

Скомпилируйте вашу программу:

$ gcc -c -o eg2.o eg2.c

Попробуйте связать вашу программу с сайт libz и не:

$ gcc -o eg2 -lz eg2.o eg2.o: In function `main’:eg2.c:(.text+0x5): undefined reference to `zlibVersion’collect2: error: ld returned 1 exit status

Если же вы скомпилировать и скомпоновать на одном дыхании:

$ gcc -o eg2 -I. -lz eg2.c/tmp/ccxCiGn7.o: In function `main’:eg2.c:(.text+0x5): undefined reference to `zlibVersion’collect2: error: ld returned 1 exit status

И вариация на примере 2, с участием

ПКГ-конфиг

:

$ gcc -o eg2 $(pkg-config –libs zlib) eg2.o eg2.o: In function `main’:eg2.c:(.text+0x5): undefined reference to `zlibVersion’

Что ты делаешь не так?

В последовательности объектных файлов и библиотек, которые вы хотите связать, чтобы сделать вашпрограммы, вы размещаете библиотеки до объектные файлы, которые относятся ких. Вам нужно разместить библиотек после объектные файлы, которые относятсяк ним.Правильно ссылку примере 1:

$ gcc -o eg1 eg1.o -L. -lmy_lib

Успех:

$ ./eg1 Hello World

Пример ссылки 2 Правильно:

$ gcc -o eg2 eg2.o -lz

Успех:

$ ./eg2 1.2.8

Ссылка на пример 2 `ПКГ-конфиг варианте правильно:

$ gcc -o eg2 eg2.o $(pkg-config –libs zlib) $ ./eg21.2.8

Объяснение

Значение является необязательным отсюда на.По умолчанию, команды связи, порожденные ССЗ, в вашем дистрибутиве,потребляет файлов в связь слева направо впоследовательность командной строки. Когда он обнаруживает, что файл относится к что-тои не содержит определение для него, чтобы искать определениев файлы дальше направо. Если он в конце концов находит определениюссылка будет решен. Если какие-либо ссылки остаются неразрешенными на конец,связь терпит неудачу: компоновщик не найти назад.Во-первых, Пример 1, со статической библиотеки my_lib.аСтатическая библиотека-это индексный архив объектных файлов. Когда компоновщикнаходит-lmy_libв последовательности, взаимосвязи и поймет, что это означает в статическую библиотеку./libmy_lib.а, он хочет знать, является ли ваша программа должен какой-либо из объектных файлов в libmy_lib.а.Есть только объектный файл в libmy_lib.а, а именноmy_lib.о, и там’s только одна вещь, определеннымив my_lib.о’, а именно функция гв.Компоновщик будет решать, что my_lib вашим потребностям программы.o, если и только если он уже знает, что ваша программа относится кГВ, в один или несколько объектных файлов, уже добавлены в программу, и что ни одна из объектных файлов уже добавлены содержит определение дляГВ. Если это правда, то компоновщик будет извлечь копиюmy_lib.оиз библиотеки и добавьте его в вашу программу. Затем, ваша программа содержит определение дляГВ, так его ссылки нааппаратный` являются решен.При попытке перейти по ссылке программы как:

$ gcc -o eg1 -L. -lmy_lib eg1.o

компоновщик не добавлены eg1.о программы когда он видит-lmy_lib. Потому что на тот момент, он не видел eg1.о. Ваша программа еще не делает никаких ссылок наГВ: это пока не делает каких-либо ссылок *на все*, потому что все ссылки это делает в eg1.о.Так что компоновщик не добавить my_lib.о программе и не имеет никаких дальнейших использовать для libmy_lib.а.Далее, он находит eg1.O, и добавляет его к программе. Объектный файл в последовательность связь всегда добавляется в программу. Теперь программа делает ссылка наГВ, и не содержит определенияаппаратный; но там ничего не осталось в последовательность связей, которые могут предоставить недостающую определение. Ссылка нагвзаканчивается *нерешенные*, и связь не удается. Во-вторых, **пример 2**, с общей библиотекисайт libz Общая библиотека это’т архив объектных файлов или чего-то подобного. Это’ы гораздо больше похоже на *программы* это вовсе’t имеют функцииmainи вместо этого предоставляет несколько другие символы, которые он определяет, так что другие программы могут использовать их во время выполнения. Многие дистрибутивы Linux уже сейчас настроить их набора инструментов GCC так, чтобы его драйверы языка (ССЗ,г++,поставляетсяи т. д.) указывает компоновщику системы (ЛД) для связывания общей библиотеки *по мере необходимости* основы. У вас есть один из этих дистрибутивов. Это означает, что, когда компоновщик находит-ЛЗв связи последовательность, и поймет, что это относится в общую библиотеку (говорят)в/usr/lib в/x86_64 с-линукс-дистрибутив GNU/сайт libz.так, он хочет знать, есть ли какие-либо ссылки, что он добавил в свою программу, что ты’т еще определены, имеют определения, которые экспортируются сайт libzЕсли это правда, то компоновщик будет не копировать любые куски из `Сайт libz идобавить их в вашу программу; вместо этого, он будет просто доктор код вашей программытак что:-

  • Во время выполнения программы система загрузчик загрузит копию сайт libz вже, как и ваша программа, когда загружает копию вашей программы, чтобы запустить его.
  • Во время выполнения, когда ваша программа ссылается на то, что определяется всайт libz, что ссылка использует определение экспортируемых копию сайт libz втот же самый процесс.Ваша программа хочет обратиться к только одна вещь, которая имеет определение экспортируемых сайт libz,а именно zlibVersion функции, который упоминается только один раз, в eg2.с.Если компоновщик добавляет, что ссылка на вашу программу, а затем находит определениеэкспортировать на сайт libz, ссылка будет *решен* Но при попытке перейти по ссылке программы как: gcc -o eg2 -lz eg2.o порядок событий является неправильным, так же, как и в Примере 1. В тот момент, когда компоновщик находит-ЛЗ – нет нет ссылки на что-либов программе: все они eg2.о, который еще не видел. Так линкер решает, что нет смысла сайт libz. Когда она достигает eg2.о, добавляет в программу,а потом неопределенная ссылка на zlibVersion, последовательность сшивания завершена;эта ссылка нерешенным, и связь не удается.Наконец, вариации `ПКГ-конфиг из примера 2 имеет сейчас очевидное объяснение.После оболочки-расширения:gcc -o eg2 $(pkg-config –libs zlib) eg2.o

становится:

gcc -o eg2 -lz eg2.o

что это просто пример 2 раз.

Я могу воспроизвести проблему в Примере 1, но не в Примере 2

Связь:

gcc -o eg2 -lz eg2.o

работает просто отлично для вас!(Или: что связь работала нормально для вас, скажем, в Fedora 23, но не на Ubuntu 16.04)Что’s, потому что в дистро, на котором связь строительство является одной из тех, чтоне настроить своего тулчейна GCC для соединения разделяемых библиотек по мере необходимости.Назад в день, это нормально для UNIX-подобных систем, связывающих статические и разделяемыебиблиотеки по разным правилам. Статические библиотеки в последовательности связей были связанына по мере необходимости основой описано в Примере 1, но общей библиотеки были безоговорочно взаимосвязаны.Такое поведение является экономичным при linktime, поскольку компоновщик не’т придется задуматьсябудь разделяемой библиотекой требуется программа: если это’ы общей библиотекисвязать его. И большинство библиотек в большинстве связей разделяемых библиотек. Но есть и недостатки:-

  • Это неэкономично по среда, потому что это может привести к общей библиотекизагружается вместе с программой, даже если не’т нуждаются в них.
  • Различные правила связывания для статических и динамических библиотек могут ввести в заблуждениедля неопытных программистов, которые, возможно, не знаете ли-lfoo в их взаимосвязисобирается решать в /какой/где/libfoo.A или на `/какой/где/libfoo.так,и не может понять разницу между общей и статической библиотекив любом случае.Этот компромисс привел к Сегодня раскольнического ситуации. Некоторые дистрибутивы имеютизменил своим правилам ССЗ для общих библиотек, так что по мере необходимостипринцип применяется для всех библиотек. Некоторые дистрибутивы пристали со старымпуть.

    Почему я все еще получаю эту проблему даже если я компиляции и компоновки в то же время?

    Если я просто делаю:

    $ gcc -o eg1 -I. -L. -lmy_lib eg1.c

конечно ССЗ приходится компилировать eg1.с первым, а затем связать полученные объектный файл с libmy_lib.а. Так как он не может знать, что объектный файлнеобходимо, когда он’ы делаешь связь?Потому что компиляция и связывание с одной командой не меняетпоследовательность сшивания.Когда вы выполните команды выше, GCC цифры, что вы хотите компиляция +связь. Так что за кадром, он создает команду компиляции и работаетего, затем создает командной связи, и запускает его, как если вы должны были запуститьдве команды:

$ gcc -I. -c -o eg1.o eg1.c$ gcc -o eg1 -L. -lmy_lib eg1.o

Так что связь не так же, как если вы действительно выполните эти две команды. Вединственное отличие Вы заметите в ошибки в том, что ССЗ породилавременный объект файл в компиляцию + ссылка случае, потому что вы’повторно не рассказыватьдля eg1.о`. Мы видим:

/tmp/ccQk1tvs.o: In function `main’

вместо:

eg1.o: In function `main’:

См. также

Порядок, в котором указываются взаимозависимыми связан библиотеки является неправильнымПоставив взаимозависимых библиотек в неправильном порядке-один из способовв котором вы можете получить файлы, которые нужно определения вещейпозднее, в связи, чем файлы, которые обеспечивают определения. Ставит библиотеки передобъектные файлы, которые ссылаются на них-еще один способ сделать ту же ошибку.

Возможные причины

Существует множество способов получения этой ошибки. Все они используют ссылку на функцию или переменную, которую компоновщику не удалось Разрешить, или найти определение для. Компилятор может определить, когда символ не объявлен, но не может определить, не определенли символ. Это связано с тем, что определение может находиться в другом исходном файле или библиотеке. Если символ упоминается, но не определен, компоновщик создает неразрешенную extern ошибку символа Al.

Ниже приведены некоторые распространенные проблемы, вызывающие ошибку LNK2019.

Исходный файл, содержащий определение символа, не скомпилирован

В Visual Studio убедитесь, что исходный файл, определяющий символ, компилируется как часть проекта. Проверьте промежуточный каталог выходных данных сборки на наличие соответствующего OBJ-файла. Если исходный файл не компилируется, щелкните его правой кнопкой мыши в обозреватель решений и выберите пункт Свойства , чтобы проверить свойства файла. На странице Свойства конфигурации > Общие должен отображаться тип элемента компилятора C/C++. В командной строке убедитесь, что исходный файл, содержащий определение, скомпилирован.

Объектный файл или библиотека, содержащие определение символа, не связаны

Убедитесь, что в Visual Studio объектный файл или библиотека, содержащие определение символа, связаны как часть проекта. В командной строке убедитесь, что список файлов для связывания содержит объектный файл или библиотеку.

Объявление символа написано не так, как определение символа

Проверьте правильность написания и регистра символов в объявлении и определении, а также в любом месте, где используется или вызывается символ.

Используется функция, но тип или число параметров не соответствуют определению функции

Объявление функции должно соответствовать определению. Убедитесь, что вызов функции соответствует объявлению и что объявление соответствует определению. Код, который вызывает функции шаблона, также должен иметь совпадающие объявления функции шаблона, включающие те же параметры шаблона, что и определение. Пример несоответствия объявления шаблона см. в разделе Sample LNK2019e. cpp статьи “примеры”.

Функция или переменная объявлена, но не определена

Ошибка LNK2019 может возникать, если объявление существует в файле заголовка, но соответствующее определение не реализовано. Для функций элементов или static элементов данных реализация должна включать селектор области класса. Пример см. в разделе Missing Function Body or Variable.

Соглашение о вызовах отличается между объявлением функции и определением функции.

Соглашения о вызовах ( __cdecl , __stdcall , __fastcall или __vectorcall ) кодируются как часть декорированного имени. Убедитесь, что соглашение о вызовах одинаково.

Символ определен в файле C, но объявлен без использования extern “C” в файле C++

Символы, определенные в файле, который компилируется как C, имеют разные декорированные имена, чем символы, объявленные в файле C++, если не используется модификатор extern “C” . Убедитесь, что объявление соответствует компоновке компиляции для каждого символа. Аналогично, если символ определяется в файле C++, который будет использоваться программой C, в определении следует использовать extern “C” .

Символ определяется как static , а затем на него указывает ссылка за пределами файла

В C++, в отличие от C, Глобальная const Ants имеет static компоновку. Чтобы обойти это ограничение, можно включить const инициализацию в файл заголовка и включить этот заголовок в cpp-файлы. Кроме того, можно сделать переменную const Ant и использовать const ссылку Ant для доступа к ней.

staticЧлен класса не определен

staticЧлен класса должен иметь уникальное определение или будет нарушать правило одного определения. staticЧлен класса, который не может быть определен как встроенный, должен быть определен в одном исходном файле с помощью его полного имени. Если он не определен вообще, компоновщик создает ошибку LNK2019.

Зависимость сборки определяется только в качестве зависимости проекта в решении

В более ранних версиях Visual Studio было достаточно этого уровня зависимостей. Однако начиная с Visual Studio 2010 для Visual Studio требуется ссылка междупроектами. Если в проекте нет ссылки проекта на проект, может возникнуть Эта ошибка компоновщика. Чтобы устранить ошибку, добавьте ссылку одного проекта на другой.

Точка входа не определена

Код приложения должен определять соответствующую точку входа: main или wmain для консольных приложений, WinMain или wWinMain для приложений Windows. Дополнительные сведения см. в разделе main функция и аргументы командной строки или WinMain функция. Чтобы использовать настраиваемую точку входа, укажите параметр компоновщика /Entry (символ точки входа) .

Построение консольного приложения с помощью параметров для приложения Windows

Если сообщение об ошибке похоже на неразрешенный extern символ Al, WinMain указанный в функции function_name, СВЯЖИТЕ с помощью параметра /SUBSYSTEM: Console вместо /SUBSYSTEM: Windows. Дополнительные сведения об этом параметре и инструкции о том, как задать это свойство в Visual Studio, см. в статье /SUBSYSTEM (Specify Subsystem).

Вы пытаетесь связать 64-разрядные библиотеки с 32-битным кодом или 32-bit Library в 64-разрядный код.

Библиотеки и объектные файлы, связанные с вашим кодом, должны быть скомпилированы для той же архитектуры, что и код. Убедитесь, что библиотеки, на которые ссылается проект, компилируются для той же архитектуры, что и проект. Убедитесь, что свойство /libpath или Дополнительные каталоги библиотек указывает на библиотеки, созданные для правильной архитектуры.

Для встраивания функций в разные исходные файлы используются различные параметры компилятора

Использование встроенных функций, определенных в CPP-файлах, и смешение в различных исходных файлах параметров компилятора для встраивания функций может привести к возникновению ошибки LNK2019. Для получения дополнительной информации см. Function Inlining Problems.

Автоматические переменные используются вне области действия

Автоматические переменные (области видимости функции) могут использоваться только в области видимости данной функции. Эти переменные нельзя объявлять extern и использовать в других исходных файлах. Пример см. в разделе Automatic (Function Scope) Variables.

Вы вызываете встроенные функции или передайте типы аргументов в встроенные функции, которые не поддерживаются в целевой архитектуре.

Например, если вы используете AVX2 встроенную функцию, но не указываете параметр компилятора / ARCH : AVX2 , компилятор предполагает, что встроенная функция является extern функцией Al. Вместо создания встроенной инструкции компилятор создает вызов extern символа Al с тем же именем, что и встроенная инструкция. Когда компоновщик пытается найти определение этой отсутствующей функции, он создает ошибку LNK2019. Убедитесь, что используются только встроенные функции и типы, поддерживаемые целевой архитектурой.

Вы занимаетесь смешением кода, который использует собственный wchar_t код с кодом, который не

Действия по согласованности языка C++, выполненные в Visual Studio 2005, сделали wchar_t собственный тип по умолчанию. Если не все файлы были скомпилированы с использованием одних и тех же параметров **/Zc: wchar_t ** , ссылки типа могут не разрешаться в совместимые типы. Убедитесь wchar_t , что типы во всех файлах библиотек и объектов совместимы. Либо обновите из wchar_t определения типа, либо используйте соответствующие параметры **/Zc: wchar_t ** при компиляции.

Решение

Вы пытались установить статическую переменную MyGame вверху файла .cpp?

Создает эту ошибку, если нигде не установлено.

Проблемы с библиотекой сторонних производителей и vcpkg

Если вы видите эту ошибку при попытке настроить библиотеку стороннего производителя в рамках сборки, рассмотрите возможность использования vcpkg, диспетчера пакетов C++ для установки и сборки библиотеки. vcpkg поддерживает большой и растущей список библиотек сторонних производителей. Он задает все свойства конфигурации и зависимости, необходимые для успешной сборки в рамках проекта.

Причины и решения

Возможных причин появления ошибки может быть несколько и это зависит от того, что представляет из себя собираемый проект. Всё множество ситуаций можно разбить на две большие группы:

Используются сторонние библиотеки

  • Не указана необходимая (статическая) библиотека для компоновщика.

    Например, к проекту подключен только *.h файл с объявлениями, но отсутствует код реализации, обычно это *.lib или *.a файлы (в зависимости от используемой системы).Требуется явно подключить библиотеку к проекту.

  • Для Visual C++ это можно сделать добавлением следующей строки прямо в код:

    #pragma comment(lib, “libname.lib”)

  • Для gcc/clang требуется указать файл через ключ -l (эль)

  • Для Qt в .pro файле нужно использовать переменную LIBS:

    LIBS += -L[путь_к_библиотеке] -l[имя_библиотеки]

  • Для системы сборки cmake есть target_link_libraries.

  • Библиотека указана, но необходимая сущность, например, класс или функция фактически не экспортируется из библиотеки. Под Windows это может возникать из-за отсуствия __declspec(dllexport) перед сущностью. Обычно это решается макросами. Данная ситуация чаще всего характерна именно для библиотек, находящихся в процессе разработки, и доступных для модификации самому разработчику, нежели для каких-то стабильных версий действительно внешних для проекта библиотек. После разрешения экспортирования библиотеку, конечно же, нужно пересобрать перед непосредственным использованием проблемной сущности.

  • Библиотека указана, но не совпадает разрядность библиотеки и компилируемого кода.

    В общем случае, разрядность собираемого проекта (приложения или библиотеки) должна совпадать с разрядностью используемой сторонней библиотеки. Обычно производители библиотек предоставляют возможность выбора 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) { // тело функции}

    Может быть ещё частный случай с ошибкой вида:

    undefined reference to `vtable for <имя_класса>`

    Такая ошибка возникает, если объявленная виртуальная функция класса, не являющаяся чистой (=0), не содержит реализации.

    class C { virtual void f(int);};

    Нужно такую реализацию добавить. Если это делается вне класса, надо не забыть указать имя проблемного класса, иначе это будет просто свободная функция, которая не устраняет указанную проблему:

    void C::f(int) { // виртуальная функция-член вне определения класса // тело функции } void f(int) { // свободная функция, не устраняющая проблему // тело функции }

    Аналогичная ситуация может возникать при использовании пространств имён, когда объявлении функции находится в пространстве имён:

    // В заголовочном файлеnamespace N { void f(int);};

    а при реализации указать это пространство имён забыли:

    // В файле реализацииvoid f(int) { // функция в глобальном пространстве имён, не устраняющая проблему // тело функции }namespace N {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.cppvoid f();int main() { f(); // undefined reference to `f()’}// B.cppstatic void f() {}

    Аналогичная ситуация может возникнуть при использовании безымянного пространства имен:

    // B.cppnamespace { void f() {}}

    Или даже при наличии inline у функции:

    // B.cppinline void f() {}

Дополнительные ресурсыAdditional resources

Дополнительные сведения о возможных причинах и решениях ошибки LNK2001 см. в Stack Overflow вопросе, что является неопределенной ссылкой или неразрешенной extern ошибкой символа Al и как ее исправить?.For more information about possible causes and solutions for LNK2001, see the Stack Overflow question What is an undefined reference/unresolved external symbol error and how do I fix it?.

Рейтинг
( 1 оценка, среднее 5 из 5 )
Загрузка ...