Chyba linkerů LNK2001

nevyřešený externí symbol "symbol"

Zkompilovaný kód odkazuje nebo volá symbol. Tento symbol není definován v žádné knihovně nebo souborech objektů, které linker vyhledá.

Za touto chybovou zprávou následuje závažná chyba LNK1120. Pokud chcete opravit LNK1120 chyby, nejprve opravte všechny chyby LNK2001 a LNK2019.

Existuje mnoho způsobů, jak získat chyby LNK2001. Všechny zahrnují odkaz na funkci nebo proměnnou, kterou linker nedokáže rozpoznat nebo najít definici. Kompilátor dokáže identifikovat, kdy váš kód nehlásí symbol, ale ne, když ho nedefinuje. Je to proto, že definice může být v jiném zdrojovém souboru nebo knihovně. Pokud váš kód odkazuje na symbol, ale nikdy není definovaný, linker vygeneruje chybu.

Co je nevyřešený externí symbol?

Symbol je interní název funkce nebo globální proměnné. Jedná se o formu použitého názvu nebo definovaného v kompilovaném souboru nebo knihovně. Globální proměnná je definována v souboru objektu, ve kterém je úložiště přiděleno. Funkce je definována v souboru objektu, kde je umístěn zkompilovaný kód pro tělo funkce. Externí symbol je jeden odkazovaný v jednom souboru objektu, ale definovaný v jiné knihovně nebo souboru objektu. Exportovaný symbol je ten, který je veřejně zpřístupněný souborem objektu nebo knihovnou, která ho definuje.

Chcete-li vytvořit aplikaci nebo knihovnu DLL, musí mít každý použitý symbol definici. Linker musí přeložit nebo najít odpovídající definici pro každý externí symbol odkazovaný každým souborem objektu. Linker vygeneruje chybu, když nemůže vyřešit externí symbol. To znamená, že linker nemohl najít odpovídající definici exportovaného symbolu v žádném z propojených souborů.

K této chybě může dojít:

  • Pokud projektu chybí odkaz na knihovnu (. LIB) nebo objekt (. OBJ) soubor. Pokud chcete tento problém vyřešit, přidejte do projektu odkaz na požadovanou knihovnu nebo soubor objektu. Další informace najdete v tématu lib Files as linker input.

  • Pokud má projekt odkaz na knihovnu (. LIB) nebo objekt (. OBJ) soubor, který zase vyžaduje symboly z jiné knihovny. Může k tomu dojít i v případě, že nevoláte funkce, které způsobují závislost. Pokud chcete tento problém vyřešit, přidejte do projektu odkaz na druhou knihovnu. Další informace najdete v tématu Vysvětlení klasického modelu pro propojení: Přebírání symbolů pro jízdu.

  • Pokud používáte možnosti /NODEFAULTLIB nebo /Zl . Když zadáte tyto možnosti, knihovny, které obsahují požadovaný kód, nejsou propojené s projektem, pokud je explicitně nezahrnete. Pokud chcete tento problém vyřešit, explicitně zahrňte všechny knihovny, které používáte na příkazovém řádku odkazu. Pokud při použití těchto možností uvidíte mnoho chybějících názvů funkcí CRT nebo standardní knihovny, explicitně do odkazu zahrňte knihovny CRT a knihovny DLL nebo soubory knihoven.

  • Pokud kompilujete pomocí možnosti /clr . Pravděpodobně chybí odkaz na .cctor. Další informace o tom, jak tento problém vyřešit, naleznete v tématu Inicializace smíšených sestavení.

  • Pokud při vytváření ladicí verze aplikace propodáte knihovny režimu vydávání verzí. Podobně pokud používáte možnosti /MTd nebo /MDd nebo definujete a pak propojit _DEBUG s knihovnami vydaných verzí, měli byste očekávat mnoho potenciálních nevyřešených externích, mimo jiné problémů. Propojení sestavení režimu vydávání verzí s ladicím knihovnami také způsobuje podobné problémy. Pokud chcete tento problém vyřešit, ujistěte se, že v buildech ladění používáte knihovny ladění a maloobchodní knihovny v prodejních buildech.

  • Pokud kód odkazuje na symbol z jedné verze knihovny, ale propočítáte jinou verzi knihovny. Obecně platí, že nemůžete kombinovat objektové soubory nebo knihovny vytvořené pro různé verze kompilátoru. Knihovny, které jsou dodávány v jedné verzi, můžou obsahovat symboly, které nelze najít v knihovnách zahrnutých v jiných verzích. Pokud chcete tento problém vyřešit, před propojením sestavte všechny soubory objektů a knihovny se stejnou verzí kompilátoru. Další informace naleznete v tématu Binární kompatibilita jazyka C++ mezi verzemi sady Visual Studio.

  • Pokud jsou cesty knihovny zastaralé. Dialogové okno Nástroje > Možnosti > projektů > VC++ v části Soubory knihovny umožňuje změnit pořadí hledání knihovny. Složka Linker v dialogovém okně Stránky vlastností projektu může obsahovat také cesty, které by mohly být zastaralé.

  • Když je nainstalována nová sada Windows SDK (možná do jiného umístění). Aby bylo možné odkazovat na nové umístění, musí být pořadí hledání knihovny aktualizováno. Za normálních okolností byste měli umístit cestu k novým sadám SDK, včetně adresářů lib před výchozí umístění Visual C++. Projekt obsahující vložené cesty může stále odkazovat na staré cesty, které jsou platné, ale zastaralé. Aktualizujte cesty pro nové funkce přidané novou verzí, která je nainstalovaná do jiného umístění.

  • Pokud sestavíte na příkazovém řádku a vytvoříte vlastní proměnné prostředí. Ověřte, že cesty k nástrojům, knihovnám a souborům hlaviček přecházejí na konzistentní verzi. Další informace naleznete v tématu Použití sady nástrojů MSVC z příkazového řádku.

Problémy s kódováním

Příčinou této chyby může být:

  • Neshoda případů ve zdrojovém kódu nebo souboru definice modulu (.def). Pokud například pojmenujete proměnnou var1 v jednom zdrojovém souboru C++ a pokusíte se k ní získat přístup jako VAR1 v jiném, vygeneruje se tato chyba. Pokud chcete tento problém vyřešit, používejte konzistentně napsané názvy a názvy velkých a malých písmen.

  • Projekt, který používá vkládání funkcí Může k tomu dojít, když definujete funkce jako inline ve zdrojovém souboru, nikoli v souboru záhlaví. Vložené funkce se nedají zobrazit mimo zdrojový soubor, který je definuje. Pokud chcete tento problém vyřešit, definujte vložené funkce v záhlavích, kde jsou deklarovány.

  • Volání funkce jazyka C z programu C++ bez použití extern "C" deklarace pro funkci jazyka C. Kompilátor používá různé zásady vytváření názvů interních symbolů pro kód jazyka C a C++. Interní název symbolu je to, co linker hledá při překladu symbolů. Chcete-li tento problém vyřešit, použijte obálku extern "C" kolem všech deklarací funkcí jazyka C, které se používají v kódu jazyka C++, což způsobí, že kompilátor použije pro tyto symboly interní konvenci pojmenování jazyka C. Možnosti kompilátoru /Tp a /Tc způsobují, že kompilátor kompiluje soubory jako C++ nebo C bez ohledu na to, co je přípona souboru. Tyto možnosti můžou způsobit, že názvy interních funkcí se liší od toho, co očekáváte.

  • Pokus o odkazování na funkce nebo data, která nemají externí propojení. V jazyce C++ mají vložené funkce a const data interní propojení, pokud nejsou explicitně zadány jako extern. Pokud chcete tento problém vyřešit, použijte explicitní extern deklarace symbolů odkazujících mimo definující zdrojový soubor.

  • Chybějící definice těla nebo proměnné funkce. Tato chyba je běžná, když deklarujete, ale nedefinujete proměnné, funkce nebo třídy v kódu. Kompilátor potřebuje pouze prototyp funkce nebo extern deklaraci proměnné k vygenerování souboru objektu bez chyby, ale linker nemůže přeložit volání funkce nebo odkaz na proměnnou, protože není vyhrazený žádný kód funkce ani prostor proměnných. Pokud chcete tento problém vyřešit, nezapomeňte definovat všechny odkazované funkce a proměnné ve zdrojovém souboru nebo knihovně, které propočítáte.

  • Volání funkce, které používá návratové a parametry nebo konvence volání, které neodpovídají konvencím v definici funkce. V souborech objektů jazyka C++ zakóduje dekorace Name konvenci volání, obor názvů nebo obor názvů a vrací a typy parametrů funkce. Kódovaný řetězec se stane součástí konečného názvu zdobené funkce. Tento název používá linker k překladu nebo porovnávání volání funkce z jiných souborů objektů. Pokud chcete tento problém vyřešit, ujistěte se, že deklarace funkce, definice a volání používají stejné obory, typy a konvence volání.

  • Kód C++, který voláte, když do definice třídy zahrnete prototyp funkce, ale nezahrnuje implementaci funkce. Pokud chcete tento problém vyřešit, nezapomeňte zadat definici pro všechny členy třídy, které voláte.

  • Pokus o volání čistě virtuální funkce z abstraktní základní třídy. Čistá virtuální funkce nemá žádnou implementaci základní třídy. Pokud chcete tento problém vyřešit, ujistěte se, že jsou implementované všechny volané virtuální funkce.

  • Pokoušíte se použít proměnnou deklarovanou v rámci funkce (místní proměnné) mimo obor této funkce. Pokud chcete tento problém vyřešit, odeberte odkaz na proměnnou, která není v oboru, nebo přesuňte proměnnou do vyššího oboru.

  • Když sestavíte verzi projektu ATL, vytvoří se zpráva, že je vyžadován spouštěcí kód CRT. Pokud chcete tento problém vyřešit, udělejte jednu z následujících věcí:

    • Odebrání _ATL_MIN_CRT ze seznamu preprocesoru definuje, aby bylo možné zahrnout spouštěcí kód CRT. Další informace naleznete na stránce obecné vlastnosti (Projekt).a0>

    • Pokud je to možné, odeberte volání funkcí CRT, které vyžadují spouštěcí kód CRT. Místo toho použijte jejich ekvivalenty Win32. Například místo lstrcmp .strcmp Známé funkce, které vyžadují spouštěcí kód CRT, jsou některé funkce řetězce a plovoucí desetinné čárky.

Problémy s konzistencí

V současné době neexistuje žádný standard pro dekoraci názvů C++ mezi dodavateli kompilátoru nebo dokonce mezi různými verzemi stejného kompilátoru. Soubory objektů zkompilované s různými kompilátory nemusí používat stejné schéma pojmenování. Propojení může způsobit chybu LNK2001.

Kombinování možností vložené a neline kompilace v různých modulech může způsobit LNK2001. Pokud se vytvoří knihovna jazyka C++ se zapnutou funkcí (/Ob1 nebo /Ob2), ale odpovídající hlavičkový soubor popisující funkce má vypnuté vkládání (bez inline klíčového slova), dojde k této chybě. Pokud chcete tento problém vyřešit, definujte funkce inline v souboru záhlaví, který zahrnete do jiných zdrojových souborů.

Pokud používáte direktivu kompilátoru #pragma inline_depth , ujistěte se, že jste nastavili hodnotu 2 nebo vyšší, a ujistěte se, že používáte také možnost kompilátoru /Ob1 nebo /Ob2 .

K této chybě může dojít, pokud při vytváření knihovny DLL jen pro prostředky vynecháte možnost /NOENTRY. Pokud chcete tento problém vyřešit, přidejte do příkazu propojení možnost /NOENTRY.

K této chybě může dojít v případě, že v projektu použijete nesprávné nastavení /SUBSYSTEM nebo /ENTRY. Pokud například napíšete konzolovou aplikaci a zadáte /SUBSYSTEM:WINDOWS, vygeneruje se nevyřešená externí chyba pro WinMain. Pokud chcete tento problém vyřešit, ujistěte se, že odpovídá možnostem typu projektu. Další informace o těchto možnostech a vstupních bodech najdete v možnostech linkeru /SUBSYSTEM a /ENTRY .

Problémy se symboly exportovaného souboru .def

K této chybě dochází v případě, že se nenašel export uvedený v souboru .def. Důvodem může být to, že export neexistuje, je nesprávně napsaný nebo používá názvy zdobené jazykem C++. Soubor .def nepřebírá zdobené názvy. Pokud chcete tento problém vyřešit, odeberte nepotřebné exporty a použijte extern "C" deklarace pro exportované symboly.

Vyhledání chyby pomocí upraveného názvu

Kompilátor jazyka C++ a linker používají funkci Name Decoration, která se označuje také jako název-mangling. Dekorace názvu kóduje další informace o typu proměnné v názvu symbolu. Název symbolu funkce kóduje svůj návratový typ, typy parametrů, obor a konvenci volání. Tento zdobený název je název symbolu, který linker hledá k překladu externích symbolů.

Chyba propojení může vést k tomu, že deklarace funkce nebo proměnné přesně neodpovídá definici funkce nebo proměnné. Je to proto, že jakýkoli rozdíl se stane součástí názvu symbolu, který se má shodovat. K chybě může dojít i v případě, že se stejný hlavičkový soubor používá jak ve volajícím kódu, tak v definovaném kódu. Jedním ze způsobů, jak k tomu může dojít, je, když zkompilujete zdrojové soubory pomocí různých příznaků kompilátoru. Pokud je například kód zkompilován tak, aby používal __vectorcall konvenci volání, ale propočítáte knihovnu, která očekává, že klienti ji budou volat pomocí výchozí __cdecl__fastcall nebo volající konvence. V tomto případě se symboly neshodují, protože konvence volání se liší.

Pokud chcete zjistit příčinu, zobrazí se v chybové zprávě dvě verze názvu. Zobrazí popisný název, název použitý ve zdrojovém kódu i zdobený název (v závorkách). Nemusíte vědět, jak interpretovat zdobený název. Pořád ho můžete hledat a porovnávat s jinými zdobenými jmény. Nástroje příkazového řádku vám můžou pomoct najít a porovnat očekávaný název symbolu a skutečný název symbolu:

  • Tady jsou užitečné možnosti /EXPORT a /SYMBOLS nástroje příkazového řádku DUMPBIN. Můžou vám pomoct zjistit, které symboly jsou definovány v souborech .dll a objektu nebo knihovny. Seznam symbolů můžete použít k ověření, že exportované zdobené názvy odpovídají zdobeným názvům, které linker hledá.

  • V některých případech může linker hlásit pouze zdobený název symbolu. Pomocí nástroje příkazového řádku UNDNAME můžete získat nedekódovanou formu dekorovaného názvu.

Další prostředky

Další informace najdete v tématu " Co je nedefinovaný odkaz nebo nevyřešená chyba externího symbolu a jak to opravit?".