链接器工具错误 LNK2019Linker Tools Error LNK2019

extern函数 "function" 中引用了未解析的 al 符号 "symbol"unresolved external symbol 'symbol' referenced in function 'function'

已编译的 函数的函数符号进行引用或调用,但是链接器在要链接的任何库或对象文件中都找不到符号定义。The compiled code for function makes a reference or call to symbol, but the linker can't find the symbol definition in any of the libraries or object files to link.

此错误消息后跟严重错误 LNK1120This error message is followed by fatal error LNK1120. 若要修复错误 LNK1120,必须先修复所有 LNK2001 和 LNK2019 错误。To fix error LNK1120, you must fix all LNK2001 and LNK2019 errors first.

可能的原因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. 有关模板声明不匹配的示例,请参阅示例部分中的示例 LNK2019e。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 VariableFor 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 不同, global const 蚂蚁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 为控制台应用程序和 WinMainwWinMain 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.

使用 Windows 应用程序的设置生成控制台应用程序You build a console application by using settings for a Windows application

如果错误消息类似于函数function_name ** extern WinMain 中引用的无法解析的 al 符号**,则使用 /SUBSYSTEM:控制台(而不是 /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).

链接到代码的库和对象文件必须编译为与代码相同的体系结构。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 ProblemsFor 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) VariablesFor 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

默认情况下,在 Visual Studio 2005 中完成的 c + + 语言一致性工作 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. 请从 typedef 中更新 wchar_t ,或在编译时使用一致的 **/zc: wchar_t **设置。Either update from a wchar_t typedef, or use consistent /Zc:wchar_t settings when you compile.

第三方库问题和 vcpkgThird-party library issues and vcpkg

如果尝试在生成过程中配置第三方库时遇到此错误,请考虑使用 vcpkg(c + + 程序包管理器)安装和生成库。If you see this error when you're trying to configure a third-party library as part of your build, consider using vcpkg, a C++ package manager, to install and build the library. vcpkg 支持较大和不断增长 的第三方库列表vcpkg supports a large and growing list of third-party libraries. 它将成功生成所需的所有配置属性和依赖项设置为项目的一部分。It sets all the configuration properties and dependencies required for successful builds as part of your project.

诊断工具Diagnosis tools

有时很难判断链接器无法找到特定的符号定义的原因。Sometimes it's difficult to tell why the linker can't find a particular symbol definition. 通常,问题是您在生成中未包含包含定义的代码。Often the problem is that you haven't included the code that contains the definition in your build. 或者,生成选项已为 al 符号创建了不同的修饰名称 extern 。Or, build options have created different decorated names for external symbols. 有多种工具和选项可以帮助你诊断 LNK2019 错误。There are several tools and options that can help you diagnose LNK2019 errors.

  • /VERBOSE链接器选项可帮助你确定链接器引用了哪些文件。The /VERBOSE linker option can help you determine which files the linker references. 此选项可帮助您验证您的生成中是否包括包含符号定义的文件。This option can help you verify whether the file that contains the definition of the symbol is included in your build.

  • /EXPORTS实用工具的和 /SYMBOLS 选项 DUMPBIN 可帮助你发现 .dll 和对象或库文件中定义了哪些符号。The /EXPORTS and /SYMBOLS options of the DUMPBIN utility can help you discover which symbols are defined in your .dll and object or library files. 请确保导出的修饰名与链接器搜索的修饰名称匹配。Make sure the exported decorated names match the decorated names the linker searches for.

  • UNDNAME 实用工具可以显示修饰名称的等效未修饰 extern al 符号。The UNDNAME utility can show you the equivalent undecorated external symbol for a decorated name.

示例Examples

以下是一些导致 LNK2019 错误的代码示例,以及关于如何修复错误的信息。Here are several examples of code that causes a LNK2019 error, together with information about how to fix the error.

声明了符号,但是未对其进行定义A symbol is declared but not defined

在此示例中, extern 声明了 al 变量但未对其进行定义:In this example, an external variable is declared but not defined:

// LNK2019.cpp
// Compile by using: cl /EHsc /W4 LNK2019.cpp
// LNK2019 expected
extern char B[100];   // B isn't available to the linker
int main() {
   B[0] = ' ';   // LNK2019
}

下面是另一个示例,其中变量和函数声明为 extern 但未提供定义:Here is another example where a variable and function are declared as extern but no definition is provided:

// LNK2019c.cpp
// Compile by using: cl /EHsc LNK2019c.cpp
// LNK2019 expected
extern int i;
extern void g();
void f() {
   i++;
   g();
}
int main() {}

除非 ig 是在生成中包含的其中一个文件中定义的,否则链接器会生成 LNK2019。Unless i and g are defined in one of the files included in the build, the linker generates LNK2019. 你可以通过将包含定义的源代码文件作为编译的一部分包括在其中来修复错误。You can fix the errors by including the source code file that contains the definitions as part of the compilation. 或者,可以将包含定义的 .obj 文件或 .lib 文件传递到链接器。Alternatively, you can pass .obj files or .lib files that contain the definitions to the linker.

static已声明但未定义数据成员A static data member is declared but not defined

当 static 声明但未定义数据成员时,也可能出现 LNK2019。LNK2019 can also occur when a static data member is declared but not defined. 以下示例生成 LNK2019,并演示如何修复此错误。The following sample generates LNK2019, and shows how to fix it.

// LNK2019b.cpp
// Compile by using: cl /EHsc LNK2019b.cpp
// LNK2019 expected
struct C {
   static int s;
};

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

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

声明参数不匹配定义Declaration parameters don't match the definition

调用模板函数的代码必须拥有匹配的模板函数声明。Code that invokes template functions must have matching template function declarations. 声明必须包括与定义相同的模板参数。Declarations must include the same template parameters as the definition. 以下示例在用户定义的运算符上生成 LNK2019,并演示如何修复此错误。The following sample generates LNK2019 on a user-defined operator, and shows how to fix it.

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

template<class T> class
Test {
   // The operator<< declaration doesn't match the definition below:
   friend ostream& operator<<(ostream&, Test&);
   // To fix, replace the line above with the following:
   // 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;   // LNK2019 unresolved external
}

wchar_t类型定义不一致Inconsistent wchar_t type definitions

此示例创建一个 DLL,该 DLL 包含一个使用的导出 WCHAR ,该导出将解析为 wchar_tThis sample creates a DLL that has an export that uses WCHAR, which resolves to wchar_t.

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

下一个示例使用上一示例中的 DLL,并生成 LNK2019,因为类型 unsigned short*WCHAR* 不同。The next sample uses the DLL in the previous sample, and generates LNK2019 because the types unsigned short* and WCHAR* aren't the same.

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

int main() {
   func(0);
}

若要修复此错误,请将更改 unsigned shortwchar_tWCHAR ,或使用/zc 编译 LNK2019g **: wchar_t - **。To fix this error, change unsigned short to wchar_t or WCHAR, or compile LNK2019g.cpp by using /Zc:wchar_t-.

其他资源Additional resources

有关 LNK2001 的可能原因和解决方案的详细信息,请参阅 Stack Overflow 问题:未 定义的引用/未解析的 " extern 符号错误",以及如何修复该错误?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?.