다음을 통해 공유


링커 도구 오류 LNK2019

'function' 함수에서 참조된 해결되지 않은 외부 기호 'symbol'입니다.

함수에 대해 컴파일된 코드는 symbol을 참조하거나 호출하지만 링커는 라이브러리나 개체 파일에서 기호 정의를 찾을 수 없습니다.

이 오류 메시지 뒤에는 치명적인 오류 LNK1120이 표시됩니다. 오류 LNK1120을 수정하려면 먼저 모든 LNK2001 및 LNK2019 오류를 수정해야 합니다.

가능한 원인

이 오류가 발생하는 방법에는 여러 가지가 있습니다. 이들 모두에는 링커가 해결할 수 없거나 정의를 찾을 수 없는 함수나 변수에 대한 참조가 포함되어 있습니다. 컴파일러는 기호가 선언되지 않은 경우를 식별할 수 있지만 기호가 정의되지 않은 경우는 알 수 없습니다. 정의가 다른 원본 파일이나 라이브러리에 있을 수 있기 때문입니다. 기호를 참조하지만 정의되지 않은 경우 링커는 해결되지 않은 외부 기호 오류를 생성합니다.

LNK2019를 일으키는 일반적인 문제는 다음과 같습니다.

기호 정의가 포함된 원본 파일이 컴파일되지 않았습니다.

Visual Studio에서 기호를 정의하는 원본 파일이 프로젝트의 일부로 컴파일되는지 확인합니다. 일치하는 .obj 파일이 있는지 중간 빌드 출력 디렉터리를 확인합니다. 원본 파일이 컴파일되지 않은 경우 솔루션 탐색기에서 파일을 마우스 오른쪽 단추로 클릭한 다음 속성을 선택하여 파일 속성을 확인합니다. 구성 속성>일반 페이지에 C/C++ 컴파일러항목 종류가 표시되어야 합니다. 명령줄에서 정의가 포함된 원본 파일이 컴파일되었는지 확인합니다.

기호 정의가 포함된 개체 파일 또는 라이브러리가 연결되지 않았습니다.

Visual Studio에서 기호 정의가 포함된 개체 파일이나 라이브러리가 프로젝트의 일부로 연결되어 있는지 확인합니다. 명령줄에서 링크할 파일 목록에 개체 파일이나 라이브러리가 포함되어 있는지 확인합니다.

기호 선언의 철자가 기호 정의의 철자와 같지 않습니다.

선언과 정의, 그리고 기호가 사용되거나 호출되는 모든 위치에서 올바른 맞춤법과 대/소문자를 사용하는지 확인합니다.

함수가 사용되지만 매개 변수의 형식이나 개수가 함수 정의와 일치하지 않습니다.

함수 선언은 정의와 일치해야 합니다. 함수 호출이 선언과 일치하고 선언이 정의와 일치하는지 확인합니다. 함수 템플릿을 호출하는 코드에는 정의와 동일한 템플릿 매개 변수를 포함하는 일치하는 함수 템플릿 선언도 있어야 합니다. 템플릿 선언 불일치의 예는 예 섹션의 샘플 LNK2019e.cpp를 참조하세요.

함수 또는 변수가 선언되었지만 정의되지 않았습니다.

LNK2019는 헤더 파일에 선언이 있지만 일치하는 정의가 구현되지 않은 경우 발생할 수 있습니다. 멤버 함수 또는 static 데이터 멤버의 경우 구현에 클래스 범위 선택기가 포함되어야 합니다. 예제를 보려면 Missing Function Body or Variable를 참조하십시오.

함수 선언과 함수 정의 간에 호출 규칙이 다릅니다.

일부 호출 규칙(__cdecl, __stdcall, __fastcall__vectorcall)은 데코레이팅된 이름의 일부로 인코딩됩니다. 호출 규칙이 동일한지 확인합니다.

기호가 C 파일에 정의되어 있지만 C++ 파일에서는 extern "C"를 사용하지 않고 선언되었습니다.

C로 컴파일된 파일은 한정자를 사용하지 않는 한 C++ 파일에 선언된 것과 동일한 symbols 데코레이팅된 이름과 다른 데코레이팅 extern "C" 된 이름을 symbols 만듭니다. 선언이 각 기호의 컴파일 연결과 일치하는지 확인합니다. 마찬가지로, C 프로그램에서 사용할 기호를 C++ 파일에서 정의하는 경우 정의에 extern "C" 을 사용하세요.

기호는 static으로 정의된 다음 나중에 파일 외부에서 참조됩니다.

C와 달리 C++에서는 전역 상수static 링크가 있습니다. 이 제한을 해결하기 위해 헤더 파일에 const 초기화를 포함하고 .cpp 파일에 해당 헤더를 포함하거나, 변수를 비상수로 만들고 상수 참조를 사용하여 액세스할 수 있습니다.

클래스의 static 멤버가 정의되지 않았습니다.

static 클래스 멤버에는 고유한 정의가 있어야 합니다. 그렇지 않으면 단일 정의 규칙을 위반하게 됩니다. 인라인으로 정의할 수 없는 static 클래스 멤버는 정규화된 이름을 사용하여 하나의 원본 파일에 정의해야 합니다. 전혀 정의되지 않은 경우 링커는 LNK2019를 생성합니다.

빌드 종속성은 솔루션의 프로젝트 종속성으로만 정의됩니다.

이전 버전의 Visual Studio에서는 이 수준의 종속성으로 충분했습니다. 그러나 Visual Studio 2010부터 Visual Studio에는 프로젝트 간 참조가 필요합니다. 프로젝트에 프로젝트 간 참조가 없으면 이 링커 오류가 발생할 수 있습니다. 프로젝트 간 참조를 추가하여 오류를 해결하세요.

진입점이 정의되지 않았습니다.

애플리케이션 코드는 콘솔 애플리케이션의 경우 main 또는 wmain, Windows 애플리케이션의 경우 WinMain 또는 wWinMain 등 적절한 진입점을 정의해야 합니다. 자세한 내용은 main 함수 및 명령줄 인수 또는 WinMain 함수를 참조하세요. 사용자 지정 진입점을 사용하려면 /ENTRY(진입점 기호) 링커 옵션을 지정합니다.

Windows 애플리케이션에 대한 설정을 사용하여 콘솔 애플리케이션을 빌드합니다.

오류 메시지가 함수 function_name 참조되는 해결되지 않은 외부 기호 WinMain 와 유사한 경우 대신 사용하여 /SUBSYSTEM:CONSOLE /SUBSYSTEM:WINDOWS연결합니다. 이 설정에 대한 자세한 내용과 Visual Studio에서 이 속성을 설정하는 방법에 대한 지침은 /SUBSYSTEM(하위 시스템 지정)을 참조하세요.

코드에 연결된 라이브러리 및 개체 파일은 코드와 동일한 아키텍처에 대해 컴파일되어야 합니다. 프로젝트에서 참조하는 라이브러리가 프로젝트와 동일한 아키텍처에 대해 컴파일되었는지 확인합니다. /LIBPATH 또는 추가 라이브러리 디렉터리 속성이 올바른 아키텍처용으로 빌드된 라이브러리를 가리키는지 확인합니다.

여러 소스 파일에서 함수 인라이닝에 대해 여러 컴파일러 옵션을 사용합니다.

여러 소스 파일에서 .cpp 파일에 정의된 인라인된 함수를 사용하고 함수 인라이닝 컴파일러 옵션을 혼합하면 LNK2019가 발생할 수 있습니다. 자세한 내용은 Function Inlining Problems을 참조하세요.

범위 밖의 자동 변수를 사용합니다.

자동(함수 범위) 변수는 해당 함수의 범위 내에서만 사용할 수 있습니다. 이러한 변수는 extern 으로 선언할 수 없으며 다른 소스 파일에서 사용할 수 없습니다. 예제를 보려면 Automatic (Function Scope) Variables를 참조하십시오.

내장 함수를 호출하거나 대상 아키텍처에서 지원되지 않는 내장 함수에 인수 형식을 전달합니다.

예를 들어 내장 함수를 AVX2 사용하지만 컴파일러 옵션을 지정 /ARCH:AVX2 하지 않으면 컴파일러는 내장 함수가 외부 함수라고 가정합니다. 인라인 명령을 생성하는 대신 컴파일러는 내장 함수와 같은 이름의 외부 기호에 대해 호출을 생성합니다. 링커가 이 누락된 함수의 정의를 찾으려고 할 때 LNK2019가 생성됩니다. 대상 아키텍처에서 지원하는 내장 함수와 형식만 사용해야 합니다.

네이티브 wchar_t를 사용하는 코드와 그렇지 않은 코드를 혼합합니다.

Visual Studio 2005에서 수행된 C++ 언어 적합성 작업으로 인해 기본적으로 wchar_t가 네이티브 형식이 되었습니다. 일부 파일이 동일한 /Zc:wchar_t 설정을 사용하여 컴파일되지 않은 경우, 형식 참조가 호환되는 형식으로 확인되지 않을 수 있습니다. 모든 라이브러리와 개체 파일의 wchar_t 형식이 호환되는지 확인합니다. wchar_t typedef에서 업데이트하거나 컴파일할 때 일관된 /Zc:wchar_t 설정을 사용합니다.

Visual Studio 2015 이전 버전의 Visual Studio를 사용하여 빌드된 static 라이브러리가 UCRT와 연결되면 LNK2019 오류가 발생할 수 있습니다. UCRT 헤더 파일 <stdio.h>, <conio.h><wchar.h>는 이제 다양한 *printf**scanf* 변형을 inline 함수로 정의합니다. 인라인된 함수는 더 작은 공통 함수 집합으로 구현됩니다. 인라인 함수에 대한 개별 exports 함수는 일반 함수만 내보내는 표준 UCRT 라이브러리에서 사용할 수 없습니다. 이 문제를 해결하는 방법에는 몇 가지가 있습니다. 권장하는 방법은 현재 버전의 Visual Studio를 사용하여 레거시 라이브러리를 다시 빌드하는 것입니다. 라이브러리 코드가 오류를 발생시킨 *printf**scanf* 함수 정의에 표준 헤더를 사용하는지 확인합니다. 다시 빌드할 수 없는 레거시 라이브러리에 대한 또 다른 옵션은 연결하는 라이브러리 목록에 legacy_stdio_definitions.lib를 추가하는 것입니다. 이 라이브러리 파일은 UCRT 헤더에 *printf* 인라인된 함수 및 *scanf* 함수를 제공합니다symbols. 자세한 내용은 잠재적인 업그레이드 문제 개요라이브러리 섹션을 참조하세요.

타사 라이브러리 문제 및 vcpkg

빌드의 일부로 타사 라이브러리를 구성하려고 할 때 이 오류가 표시되면 vcpkg 사용을 고려해 보세요. vcpkg는 기존 Visual Studio 도구를 사용하여 라이브러리를 설치하고 빌드하는 C++ 패키지 관리자입니다. vcpkg는 점점 늘어나고 있는 타사 라이브러리 목록을 지원합니다. 프로젝트의 일부로 성공적인 빌드에 필요한 모든 구성 속성과 종속성을 설정합니다.

진단 도구

때로는 링커가 특정 기호 정의를 찾을 수 없는 이유를 파악하기 어려울 수 있습니다. 종종 문제는 빌드에 정의가 포함된 코드를 포함하지 않은 것입니다. 또는 빌드 옵션이 외부 symbols에 대해 다른 데코레이팅된 이름을 만들었습니다. LNK2019 오류를 진단하는데 도움이 되는 여러 가지 도구 및 옵션이 있습니다.

  • /VERBOSE 링커 옵션은 링커가 참조하는 파일을 결정하는 데 도움이 될 수 있습니다. 이 옵션을 통해 기호 정의를 포함하는 파일이 빌드에 포함되어 있는지 여부를 확인할 수 있습니다.

  • /EXPORTS 유틸리티 및 /SYMBOLS DUMPBIN 옵션은 .dll 및 개체 또는 라이브러리 파일에 정의된 항목을 검색 symbols 하는 데 도움이 될 수 있습니다. 내보낸 데코레이팅된 이름이 링커가 검색하는 데코레이팅된 이름과 일치하는지 확인합니다.

  • 이 유틸리티는 UNDNAME 데코레이팅된 이름에 해당하는 데코레이트되지 않은 외부 기호를 표시할 수 있습니다.

예제

다음은 LNK2019 오류를 일으키는 코드의 몇 가지 예와 오류 수정 방법에 대한 정보입니다.

기호가 선언되었지만 정의되지 않았습니다.

이 예제에서는 외부 변수가 선언되었지만 정의되지 않았습니다.

// 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으로 선언되었지만 정의가 제공되지 않은 또 다른 예입니다.

// 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를 생성합니다. 컴파일의 일부로써 정의를 포함하는 소스 코드 파일을 포함하여 오류를 해결할 수 있습니다. 또는 정의가 포함된 .obj 파일 또는 .lib 파일을 링커에 전달할 수 있습니다.

static 데이터 멤버가 선언되었지만 정의되지 않았습니다.

LNK2019는 static 데이터 멤버가 선언되었지만 정의되지 않은 경우에도 발생할 수 있습니다. 다음 샘플에서는 LNK2019가 생성되며 해결 방법을 보여 줍니다.

// 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;
}

선언 매개 변수가 정의와 일치하지 않습니다.

함수 템플릿을 호출하는 코드에는 일치하는 함수 템플릿 선언이 있어야 합니다. 선언에는 정의와 동일한 템플릿 매개 변수가 포함되어야 합니다. 다음 샘플에서는 사용자 정의 연산자에 LNK2019가 생성되고 해결 방법을 보여 줍니다.

// 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 형식 정의

이 샘플은 wchar_t로 확인되는 WCHAR를 사용하는 내보내기가 있는 DLL을 만듭니다.

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

다음 샘플은 이전 샘플의 DLL을 사용하고 unsigned short*WCHAR* 형식이 동일하지 않기 때문에 LNK2019를 생성합니다.

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

int main() {
   func(0);
}

이 오류를 해결하려면 unsigned shortwchar_t 또는 WCHAR로 변경하거나 /Zc:wchar_t-를 사용하여 LNK2019g.cpp를 컴파일합니다.

참고 항목

LNK2019, LNK2001 및 LNK1120 오류의 가능한 원인과 솔루션에 대한 자세한 내용은 스택 오버플로 질문: What is an undefined reference/unresolved external symbol error and how do I fix it?를 참조하세요.