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

Обновлен: Ноябрь 2007

Сообщение об ошибке

ссылка на неразрешенный внешний символ "символ" в функции "функция".
unresolved external symbol 'symbol' referenced in function 'function'.

Обнаружен неопределенный внешний символ (symbol) в function. Чтобы устранить эту ошибку, предоставьте определение для символа или удалите код, который на него ссылается. Дополнительные сведения см. в следующих разделах:

В следующем примере показано возникновение ошибки LNK2019:

// LNK2019.cpp
// LNK2019 expected
extern char B[100];   // B is not in avilable to the linker
int main() {
   B[0] = ' ';
}

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

// LNK2019b.cpp
// LNK2019 expected
struct C {
   static int s;
};

// Uncomment the following line to resolve.
// int C::s;

int main() {
   C c;
   C::s = 1;
}

Рассмотрим следующий пример:

// LNK2019c.cpp
// LNK2019 expected
extern int i;
extern void g();
void f() {
   i++;
   g();
}
int main() {}

Если i и g не определены в одном из файлов, включенных в построение, компоновщик создает ошибку LNK2019. Эти определения можно добавить, включив файл с исходным кодом, который содержит определения как часть компиляции. Дополнительно можно передать файлы OBJ или LIB, которые содержат определения, компоновщику.

Для проектов C++ предыдущих выпусков, обновленных до текущей версии, если __UNICODE был определен, и точка входа была WinMain, нужно изменить имя функции точки входа на _tWinMain или wWinMain.

Общие проблемы, вызывающие ошибку LNK2019:

  • Объявление символа содержит грамматические ошибки, например не совпадает имя определения и символа.

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

  • Соглашение о вызове (__cdecl, __stdcall или __fastcall) отличается от того, которое используется в объявлении и определении функции.

  • Определения символов находятся в файле, который был скомпилирован как программа C, а символы объявлены в файле C++ без внешнего модификатора "C". В этом случае измените объявление, например вместо:

    extern int i;
    extern void g();
    

    используйте:

    extern "C" int i;
    extern "C" void g();
    

    Также, если символ был определен в файле C++, который будет использоваться программой C, используйте extern "C" в определении.

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

  • Не определен статический член класса. Например, переменная члена si в объявлении класса будет определена отдельно, как показано ниже:

    // LNK2019d.cpp
    #include <stdio.h>
    struct X {
       static int si;
    };
    
    // int X::si = 0;   // uncomment this line to resolve
    
    int main() {
       X *px = new X[2];
       printf_s("\n%d",px[0].si);   // LNK2019
    }
    

В следующем примере показано возникновение ошибки LNK2019 для определенного пользователем оператора:

// LNK2019e.cpp
// compile with: /EHsc
// LNK2019 expected
#include <iostream>
using namespace std;

template<class T> class 
Test {
   friend ostream& operator<<(ostream&, Test&);
   // Uncomment the following line to resolve.
   // template<typename T> friend ostream& operator << (ostream&, Test<T>&);
};

template<typename T>
ostream& operator<<(ostream& os, Test<T>& tt) {
   return os;
}

int main() {
   Test<int> t;
   cout << "Test: " << t << endl;   // unresolved external
}

Параметр компоновщика /VERBOSE поможет увидеть, какие файлы использует компоновщик. Параметры /EXPORTS и /SYMBOLS служебной программы DUMPBIN также могут помочь увидеть, какие символы определены в DLL-файле, файлах библиотек и объектных файлах.

Дополнительные сведения об ошибке LNK2019 см. в базе знаний Майкрософт: https://support.microsoft.com (на английском языке).

Ошибка LNK2019 может также возникать в результате работы по согласованию, которая была выполнена для Visual Studio .NET 2003: понятные шаблоны и спецификации. В Visual Studio .NET 2003 объявление дружественной функции с тем же именем, как у шаблона функции, не отсылает к этому шаблону функции, пока аргументы шаблона не будут явно указаны в дружественном объявлении.

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

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

Для кода, допустимого как в версии Visual Studio .NET 2003, так и в версии Visual Studio .NET приложения Visual C++, явно объявите список аргументов шаблона дружественной функции.

// LNK2019f.cpp
// LNK2019 expected
template<class T>
void f(T) {}

template<class T>
struct S {
   friend void f(T);
   // try the folowing line instead
   // friend void f<T>(T);
};

int main() {
   S<int> s;
   f(1);   // unresolved external
}

Ошибка LNK2019 также может возникнуть в результате работы по согласованию, которая теперь выполнена в Visual C++ 2005, /Zc:wchar_t по умолчанию. Не все модули могут быть скомпилированы с тем же параметром /Zc:wchar_t, в результате чего тип ссылается на типы с нерешенной совместимостью. Чтобы решить эту проблему, убедитесь, что типы во всех модулях совместимы, выполнив компиляцию с соответствующими параметрами /Zc:wchar_t (например с использованием параметра /Zc:wchar_t- при сборке модулей с помощью набора инструментов Visual C++ 2005, который будет связан с модулями из предыдущих версий) или, если возможно, обновив типы, чтобы они стали совместимыми.

Явные ссылки на comsupp.lib из прагмы комментария или через командную строку следует изменить на comsuppw.lib или comsuppwd.lib, так как /Zc:wchar_t сейчас используется по умолчанию. Библиотеку comsupp.lib все еще следует использовать при компиляции с помощью /Zc:wchar_t-.

Дополнительные сведения см. в разделах Критические изменения в компиляторе Visual C++ 2005 и /Zc:wchar_t (wchar_t – это собственный тип).

В следующем примере создается экспорт, использующий WCHAR, который разрешается в wchar_t:

// LNK2019g.cpp
// compile with: /LD
#include "windows.h"
// WCHAR resolves to wchar_t
__declspec(dllexport) void func(WCHAR*) {}

В следующем примере показано возникновение ошибки LNK2019:

// LNK2019h.cpp
// compile with: LNK2019g.lib
// LNK2019 expected
__declspec(dllimport) void func(unsigned short*);

int main() {
   func(0);
}

Чтобы устранить эту ошибку, измените unsigned short на wchar_t или WCHAR или скомпилируйте LNK2019g.cpp с помощью /Zc:wchar_t-.

Ошибка LNK2019 может также возникнуть при сборке консольного приложения с помощью /SUBSYSTEM:WINDOWS. Неразрешенный символ будет _WinMain@16. В этом случае просто выполните компоновку с помощью /SUBSYSTEM:CONSOLE.