Bagikan melalui


LNK2019 Kesalahan Alat Linker

simbol al yang tidak terselesaikan extern'simbol' yang direferensikan dalam fungsi 'function'

Kode yang dikompilasi untuk fungsi membuat referensi atau panggilan ke simbol, tetapi linker tidak dapat menemukan definisi simbol di salah satu pustaka atau file objek.

Pesan kesalahan ini diikuti oleh kesalahan fatal LNK1120. Untuk memperbaiki kesalahan LNK1120, Anda harus memperbaiki semua kesalahan LNK2001 dan LNK2019 terlebih dahulu.

Kemungkinan penyebab

Ada banyak cara untuk mendapatkan kesalahan ini. Semuanya melibatkan referensi ke fungsi atau variabel yang tidak dapat diatasi oleh linker, atau menemukan definisi. Pengkompilasi dapat mengidentifikasi kapan simbol tidak dideklarasikan, tetapi tidak dapat mengetahui kapan simbol tidak ditentukan. Ini karena definisi mungkin berada dalam file atau pustaka sumber yang berbeda. Jika simbol dirujuk tetapi tidak pernah ditentukan, linker menghasilkan kesalahan simbol al yang tidak terselesaikan extern.

Berikut adalah beberapa masalah umum yang menyebabkan LNK2019:

File sumber yang berisi definisi simbol tidak dikompilasi

Di Visual Studio, pastikan file sumber yang menentukan simbol dikompilasi sebagai bagian dari proyek Anda. Periksa direktori output build perantara untuk file .obj yang cocok. Jika file sumber tidak dikompilasi, klik kanan file di Penjelajah Solusi, lalu pilih Properti untuk memeriksa properti file. Halaman Umum Properti>Konfigurasi harus menampilkan Tipe Item Pengkompilasi C/C++. Pada baris perintah, pastikan file sumber yang berisi definisi dikompilasi.

File objek atau pustaka yang berisi definisi simbol tidak ditautkan

Di Visual Studio, pastikan file objek atau pustaka yang berisi definisi simbol ditautkan sebagai bagian dari proyek Anda. Pada baris perintah, pastikan daftar file yang akan ditautkan menyertakan file objek atau pustaka.

Deklarasi simbol tidak dieja sama dengan definisi simbol

Pastikan Anda menggunakan ejaan dan kapitalisasi yang benar dalam deklarasi dan definisi, dan di mana pun simbol digunakan atau dipanggil.

Fungsi digunakan tetapi jenis atau jumlah parameter tidak cocok dengan definisi fungsi

Deklarasi fungsi harus cocok dengan definisi. Pastikan panggilan fungsi cocok dengan deklarasi, dan bahwa deklarasi cocok dengan definisi. Kode yang memanggil templat fungsi juga harus memiliki deklarasi templat fungsi yang cocok yang menyertakan parameter templat yang sama dengan definisi. Untuk contoh ketidakcocokan deklarasi templat, lihat contoh LNK2019e.cpp di bagian Contoh.

Fungsi atau variabel dideklarasikan tetapi tidak ditentukan

LNK2019 dapat terjadi ketika deklarasi ada dalam file header, tetapi tidak ada definisi yang cocok yang diterapkan. Untuk fungsi anggota atau static anggota data, implementasi harus menyertakan pemilih cakupan kelas. Misalnya, lihat Isi Fungsi atau Variabel yang Hilang.

Konvensi panggilan berbeda antara deklarasi fungsi dan definisi fungsi

Beberapa konvensi panggilan (__cdecl, __stdcall, __fastcall, dan __vectorcall) dikodekan sebagai bagian dari nama yang didekorasi. Pastikan konvensi panggilan sama.

Simbol didefinisikan dalam file C, tetapi dinyatakan tanpa menggunakan extern "C" dalam file C++

File yang dikompilasi sebagai C membuat nama yang didekorasi untuk simbol yang berbeda dari nama yang didekorasi untuk simbol yang sama yang dideklarasikan dalam file C++, kecuali Anda menggunakan pengubah extern "C" . Pastikan deklarasi cocok dengan tautan kompilasi untuk setiap simbol. Demikian pula, jika Anda menentukan simbol dalam file C++ yang akan digunakan oleh program C, gunakan extern "C" dalam definisi.

Simbol didefinisikan sebagai static dan kemudian dirujuk di luar file

Di C++, tidak seperti C, semut global constmemiliki static tautan. Untuk mengatasi batasan ini, Anda dapat menyertakan const inisialisasi dalam file header dan menyertakan header tersebut dalam file .cpp Anda, atau Anda dapat membuat variabel non-semutconst dan menggunakan constreferensi semut untuk mengaksesnya.

static Anggota kelas tidak ditentukan

Anggota static kelas harus memiliki definisi unik, atau akan melanggar aturan satu definisi. static Anggota kelas yang tidak dapat didefinisikan sebaris harus ditentukan dalam satu file sumber dengan menggunakan nama yang sepenuhnya memenuhi syarat. Jika tidak didefinisikan sama sekali, linker menghasilkan LNK2019.

Dependensi build hanya didefinisikan sebagai dependensi proyek dalam solusi

Di versi Visual Studio yang lebih lama, tingkat dependensi ini sudah cukup. Namun, dimulai dengan Visual Studio 2010, Visual Studio memerlukan referensi proyek-ke-proyek. Jika proyek Anda tidak memiliki referensi proyek-ke-proyek, Anda mungkin menerima kesalahan linker ini. Tambahkan referensi proyek-ke-proyek untuk memperbaikinya.

Titik masuk tidak ditentukan

Kode aplikasi harus menentukan titik masuk yang sesuai: main atau wmain untuk aplikasi konsol, dan WinMain atau wWinMain untuk aplikasi Windows. Untuk informasi selengkapnya, lihat main fungsi dan argumen atau WinMain fungsi baris perintah. Untuk menggunakan titik entri kustom, tentukan /ENTRY opsi penghubung (Simbol Titik Entri).

Anda membangun aplikasi konsol dengan menggunakan pengaturan untuk aplikasi Windows

Jika pesan kesalahan mirip dengan simbol WinMain al yang belum terselesaikan yang direferensikan externdalam fungsi function_name, tautkan dengan menggunakan /SUBSYSTEM:CONSOLE alih-alih /SUBSYSTEM:WINDOWS. Untuk informasi selengkapnya tentang pengaturan ini, dan untuk petunjuk tentang cara mengatur properti ini di Visual Studio, lihat /SUBSYSTEM (Tentukan Subsistem).

Pustaka dan file objek yang ditautkan ke kode Anda harus dikompilasi untuk arsitektur yang sama dengan kode Anda. Pastikan pustaka referensi proyek Anda dikompilasi untuk arsitektur yang sama dengan proyek Anda. Pastikan /LIBPATH properti Direktori Pustaka Tambahan menunjuk ke pustaka yang dibuat untuk arsitektur yang benar.

Anda menggunakan opsi pengkompilasi yang berbeda untuk fungsi inlining dalam file sumber yang berbeda

Menggunakan fungsi inlined yang ditentukan dalam file .cpp dan fungsi pencampuran yang menginlining opsi pengkompilasi dalam file sumber yang berbeda dapat menyebabkan LNK2019. Untuk informasi selengkapnya, lihat Masalah Inlining Fungsi.

Anda menggunakan variabel otomatis di luar cakupannya

Variabel otomatis (cakupan fungsi) hanya dapat digunakan dalam cakupan fungsi tersebut. Variabel ini tidak dapat dideklarasikan extern dan digunakan dalam file sumber lainnya. Misalnya, lihat Variabel Otomatis (Cakupan Fungsi).

Anda memanggil fungsi intrinsik atau meneruskan jenis argumen ke fungsi intrinsik yang tidak didukung pada arsitektur target Anda

Misalnya, jika Anda menggunakan intrinsik AVX2 , tetapi jangan tentukan /ARCH:AVX2 opsi pengkompilasi, pengkompilasi mengasumsikan bahwa intrinsik adalah externfungsi al. Alih-alih menghasilkan instruksi sebaris, pengkompilasi menghasilkan panggilan ke externsimbol al dengan nama yang sama dengan intrinsik. Ketika linker mencoba menemukan definisi fungsi yang hilang ini, itu menghasilkan LNK2019. Pastikan Anda hanya menggunakan intrinsik dan jenis yang didukung oleh arsitektur target Anda.

Anda mencampur kode yang menggunakan asli wchar_t dengan kode yang tidak

Pekerjaan kesesuaian bahasa C++ yang dilakukan di Visual Studio 2005 membuat wchar_t jenis asli secara default. Jika tidak semua file telah dikompilasi dengan menggunakan pengaturan yang sama /Zc:wchar_t , referensi jenis mungkin tidak mengatasi jenis yang kompatibel. Pastikan wchar_t jenis di semua pustaka dan file objek kompatibel. Perbarui dari wchar_t typedef, atau gunakan pengaturan /Zc yang konsisten :wchar_t saat Anda mengkompilasi.

static Pustaka yang dibuat menggunakan versi Visual Studio sebelum Visual Studio 2015 dapat menyebabkan kesalahan LNK2019 saat ditautkan dengan UCRT. File <stdio.h>header UCRT , <conio.h>, dan <wchar.h>sekarang menentukan banyak *printf* dan *scanf* variasi sebagai inline fungsi. Fungsi inlined diimplementasikan oleh serangkaian fungsi umum yang lebih kecil. Ekspor individual untuk fungsi inlined tidak tersedia di pustaka UCRT standar, yang hanya mengekspor fungsi umum. Ada beberapa cara untuk mengatasi masalah ini. Metode yang kami sarankan adalah membangun kembali pustaka warisan dengan versi Visual Studio Anda saat ini. Pastikan kode pustaka menggunakan header standar untuk definisi *printf* fungsi dan *scanf* yang menyebabkan kesalahan. Opsi lain untuk pustaka warisan yang tidak dapat Anda bangun ulang adalah menambahkan legacy_stdio_definitions.lib ke daftar pustaka yang Anda tautkan. File pustaka ini menyediakan simbol untuk *printf* fungsi dan *scanf* yang di-inlin di header UCRT. Untuk informasi selengkapnya, lihat bagian Pustaka di Gambaran Umum potensi masalah peningkatan.

Masalah pustaka pihak ketiga dan vcpkg

Jika Anda melihat kesalahan ini saat mencoba mengonfigurasi pustaka pihak ketiga sebagai bagian dari build Anda, pertimbangkan untuk menggunakan vcpkg. vcpkg adalah manajer paket C++ yang menggunakan alat Visual Studio yang ada untuk menginstal dan membangun pustaka. vcpkg mendukung daftar pustaka pihak ketiga yang besar dan berkembang. Ini mengatur semua properti konfigurasi dan dependensi yang diperlukan untuk build yang berhasil sebagai bagian dari proyek Anda.

Alat diagnosis

Terkadang sulit untuk mengetahui mengapa linker tidak dapat menemukan definisi simbol tertentu. Seringkali masalahnya adalah Anda belum menyertakan kode yang berisi definisi dalam build Anda. Atau, opsi build telah membuat nama yang didekorasi yang berbeda untuk externsimbol al. Ada beberapa alat dan opsi yang dapat membantu Anda mendiagnosis kesalahan LNK2019.

  • Opsi /VERBOSE linker dapat membantu Anda menentukan file mana yang dirujuk oleh linker. Opsi ini dapat membantu Anda memverifikasi apakah file yang berisi definisi simbol disertakan dalam build Anda.

  • Opsi /EXPORTS DUMPBIN dan /SYMBOLS utilitas dapat membantu Anda menemukan simbol mana yang ditentukan dalam file .dll dan objek atau pustaka Anda. Pastikan nama yang didekorasi yang diekspor cocok dengan nama yang didekorasi yang dicari linker.

  • UNDNAME Utilitas dapat menunjukkan simbol al yang tidak terdekorasi externyang setara untuk nama yang didekorasi.

Contoh

Berikut adalah beberapa contoh kode yang menyebabkan kesalahan LNK2019, bersama dengan informasi tentang cara memperbaiki kesalahan.

Simbol dideklarasikan tetapi tidak ditentukan

Dalam contoh ini, externvariabel al dideklarasikan tetapi tidak ditentukan:

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

Berikut adalah contoh lain di mana variabel dan fungsi dinyatakan sebagai extern tetapi tidak ada definisi yang disediakan:

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

Kecuali i dan g didefinisikan dalam salah satu file yang disertakan dalam build, linker menghasilkan LNK2019. Anda dapat memperbaiki kesalahan dengan menyertakan file kode sumber yang berisi definisi sebagai bagian dari kompilasi. Atau, Anda dapat meneruskan .obj file atau .lib file yang berisi definisi ke linker.

static Anggota data dinyatakan tetapi tidak ditentukan

LNK2019 juga dapat terjadi ketika static anggota data dinyatakan tetapi tidak ditentukan. Sampel berikut menghasilkan LNK2019, dan menunjukkan cara memperbaikinya.

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

Parameter deklarasi tidak cocok dengan definisi

Kode yang memanggil templat fungsi harus memiliki deklarasi templat fungsi yang cocok. Deklarasi harus menyertakan parameter templat yang sama dengan definisi. Sampel berikut menghasilkan LNK2019 pada operator yang ditentukan pengguna, dan menunjukkan cara memperbaikinya.

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

Definisi jenis yang tidak konsisten wchar_t

Sampel ini membuat DLL yang memiliki ekspor yang menggunakan WCHAR, yang diselesaikan ke wchar_t.

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

Sampel berikutnya menggunakan DLL dalam sampel sebelumnya, dan menghasilkan LNK2019 karena jenis unsigned short* dan WCHAR* tidak sama.

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

int main() {
   func(0);
}

Untuk memperbaiki kesalahan ini, ubah unsigned short ke wchar_t atau WCHAR, atau kompilasi LNK2019g.cpp dengan menggunakan /Zc:wchar_t-.

Lihat juga

Untuk informasi selengkapnya tentang kemungkinan penyebab dan solusi untuk kesalahan LNK2019, LNK2001, dan LNK1120, lihat pertanyaan Stack Overflow: What is an undefined reference/unresolved external symbol error and how do I fix it?.