Erreur des outils Éditeur de liens LNK2001

symbole externe non résolu « symbole »

Le code compilé effectue une référence ou un appel au symbole. Le symbole n’est défini dans aucune bibliothèque ou fichier objet recherché par l’éditeur de liens.

Ce message d’erreur est suivi d’une erreur irrécupérable LNK1120. Pour corriger les LNK1120 d’erreurs, corrigez tout d’abord toutes les erreurs LNK2001 et LNK2019.

Il existe de nombreuses façons d’obtenir des erreurs LNK2001. Toutes impliquent une référence à une fonction ou à une variable pour laquelle l’éditeur de liens ne peut pas résoudre ou trouver une définition. Le compilateur peut identifier quand votre code ne déclare pas de symbole, mais pas quand il ne le définit pas. Cela est dû au fait que la définition peut se trouver dans un autre fichier ou bibliothèque source. Si votre code fait référence à un symbole, mais qu’il n’est jamais défini, l’éditeur de liens génère une erreur.

Qu’est-ce qu’un symbole externe non résolu ?

Un symbole est le nom interne d’une fonction ou d’une variable globale. Il s’agit de la forme du nom utilisé ou défini dans un fichier ou une bibliothèque d’objets compilés. Une variable globale est définie dans le fichier objet où le stockage est alloué pour celui-ci. Une fonction est définie dans le fichier objet où le code compilé pour le corps de la fonction est placé. Un symbole externe est un symbole référencé dans un fichier objet, mais défini dans une autre bibliothèque ou fichier objet. Un symbole exporté est celui qui est rendu public par le fichier objet ou la bibliothèque qui le définit.

Pour créer une application ou une DLL, chaque symbole utilisé doit avoir une définition. L’éditeur de liens doit résoudre ou rechercher la définition correspondante pour chaque symbole externe référencé par chaque fichier objet. L’éditeur de liens génère une erreur lorsqu’il ne peut pas résoudre un symbole externe. Cela signifie que l’éditeur de liens n’a pas trouvé de définition de symbole exportée correspondante dans les fichiers liés.

Cette erreur peut se produire :

  • Lorsque le projet est manquant, une référence à une bibliothèque (. LIB) ou objet (. Fichier OBJ). Pour résoudre ce problème, ajoutez une référence au fichier bibliothèque ou objet requis à votre projet. Pour plus d’informations, consultez fichiers lib en tant qu’entrée de l’éditeur de liens.

  • Lorsque le projet a une référence à une bibliothèque (. LIB) ou objet (. Fichier OBJ) qui à son tour nécessite des symboles d’une autre bibliothèque. Cela peut se produire même si vous n’appelez pas de fonctions qui provoquent la dépendance. Pour résoudre ce problème, ajoutez une référence à l’autre bibliothèque à votre projet. Pour plus d’informations, consultez Présentation du modèle classique pour la liaison : Prise de symboles le long du trajet.

  • Si vous utilisez les options /NODEFAULTLIB ou /Zl . Lorsque vous spécifiez ces options, les bibliothèques qui contiennent du code requis ne sont pas liées au projet, sauf si vous les avez incluses explicitement. Pour résoudre ce problème, incluez explicitement toutes les bibliothèques que vous utilisez sur la ligne de commande de lien. Si vous voyez de nombreux noms de fonctions CRT ou Bibliothèque standard manquants lorsque vous utilisez ces options, incluez explicitement les DLL crT et les dll de bibliothèque standard ou les fichiers de bibliothèque dans le lien.

  • Si vous compilez à l’aide de l’option /clr . Il peut y avoir une référence manquante à .cctor. Pour plus d’informations sur la résolution de ce problème, consultez Initialisation des assemblys mixtes.

  • Si vous créez un lien vers les bibliothèques en mode mise en production lors de la génération d’une version de débogage d’une application. De même, si vous utilisez des options /MTd ou /MDd ou définissez_DEBUG, puis liez-vous aux bibliothèques de mise en production, vous devez vous attendre à de nombreux externes non résolus potentiels, entre autres problèmes. La liaison d’une build en mode mise en production avec les bibliothèques de débogage provoque également des problèmes similaires. Pour résoudre ce problème, veillez à utiliser les bibliothèques de débogage dans vos builds de débogage et les bibliothèques de vente au détail dans vos builds de vente au détail.

  • Si votre code fait référence à un symbole d’une version de bibliothèque, mais que vous liez une autre version de la bibliothèque. En règle générale, vous ne pouvez pas combiner de fichiers ou de bibliothèques d’objets créés pour différentes versions du compilateur. Les bibliothèques fournies dans une version peuvent contenir des symboles introuvables dans les bibliothèques incluses dans d’autres versions. Pour résoudre ce problème, générez tous les fichiers et bibliothèques d’objets avec la même version du compilateur avant de les lier ensemble. Pour plus d’informations, consultez la compatibilité binaire C++ entre les versions de Visual Studio.

  • Si les chemins de bibliothèque sont obsolètes. La boîte de dialogue Options > outils > projets > VC++ Répertoires, sous la sélection des fichiers de bibliothèque, vous permet de modifier l’ordre de recherche de la bibliothèque. Le dossier Éditeur de liens de la boîte de dialogue Pages de propriétés du projet peut également contenir des chemins pouvant être obsolètes.

  • Lorsqu’un nouveau Kit de développement logiciel (SDK) Windows est installé (peut-être à un autre emplacement). L’ordre de recherche de la bibliothèque doit être mis à jour pour pointer vers le nouvel emplacement. Normalement, vous devez placer le chemin d’accès aux nouveaux répertoires du Kit de développement logiciel (SDK) include et lib devant l’emplacement Visual C++ par défaut. En outre, un projet contenant des chemins incorporés peut toujours pointer vers les anciens chemins valides, mais obsolètes. Mettez à jour les chemins d’accès pour les nouvelles fonctionnalités ajoutées par la nouvelle version installée à un autre emplacement.

  • Si vous générez à la ligne de commande et que vous avez créé vos propres variables d’environnement. Vérifiez que les chemins d’accès aux outils, aux bibliothèques et aux fichiers d’en-tête passent à une version cohérente. Pour plus d’informations, consultez l’ensemble d’outils MSVC à partir de la ligne de commande.

Problèmes de codage

Cette erreur peut avoir les explications suivantes :

  • Cas incompatible dans votre code source ou fichier de définition de module (.def). Par exemple, si vous nommez une variable var1 dans un fichier source C++ et essayez de l’accéder comme VAR1 dans un autre, cette erreur est générée. Pour résoudre ce problème, utilisez des noms orthographiés et casés de manière cohérente.

  • Projet qui utilise l’incorporation de fonctions. Cela peut se produire lorsque vous définissez les fonctions comme inline dans un fichier source, plutôt que dans un fichier d’en-tête. Les fonctions inline ne peuvent pas être affichées en dehors du fichier source qui les définit. Pour résoudre ce problème, définissez les fonctions inline dans les en-têtes où elles sont déclarées.

  • Appel d’une fonction C à partir d’un programme C++ sans utiliser de extern "C" déclaration pour la fonction C. Le compilateur utilise différentes conventions d’affectation de noms de symboles internes pour le code C et C++. Le nom du symbole interne est ce que recherche l’éditeur de liens lors de la résolution des symboles. Pour résoudre ce problème, utilisez un extern "C" wrapper autour de toutes les déclarations de fonctions C utilisées dans votre code C++, ce qui entraîne l’utilisation de la convention d’affectation de noms interne C pour ces symboles. Les options du compilateur /Tp et /Tc entraînent la compilation des fichiers en C++ ou C, respectivement, quelle que soit l’extension de nom de fichier. Ces options peuvent entraîner des noms de fonctions internes différents de ce que vous attendez.

  • Tentative de référencer des fonctions ou des données qui n’ont pas de liaison externe. En C++, les fonctions inline et const les données ont une liaison interne, sauf indication explicite en tant que extern. Pour résoudre ce problème, utilisez des déclarations explicites extern sur les symboles référencés en dehors du fichier source de définition.

  • Corps de la fonction ou définition de variable manquant. Cette erreur est courante lorsque vous déclarez, mais que vous ne définissez pas, les variables, les fonctions ou les classes dans votre code. Le compilateur a uniquement besoin d’un prototype de fonction ou extern d’une déclaration de variable pour générer un fichier objet sans erreur, mais l’éditeur de liens ne peut pas résoudre un appel à la fonction ou une référence à la variable, car aucun code de fonction ni espace variable n’est réservé. Pour résoudre ce problème, veillez à définir chaque fonction et variable référencées dans un fichier source ou une bibliothèque que vous liez.

  • Appel de fonction qui utilise des types de retour et de paramètres ou des conventions d’appel qui ne correspondent pas à celles de la définition de fonction. Dans les fichiers objet C++, la décoration name encode la convention d’appel, la classe ou l’étendue de l’espace de noms, et retourne et les types de paramètres d’une fonction. La chaîne encodée fait partie du nom final de la fonction décorée. Ce nom est utilisé par l’éditeur de liens pour résoudre ou faire correspondre les appels à la fonction à partir d’autres fichiers d’objets. Pour résoudre ce problème, assurez-vous que la déclaration de fonction, la définition et les appels utilisent toutes les mêmes étendues, types et conventions d’appel.

  • Code C++ que vous appelez, lorsque vous incluez un prototype de fonction dans une définition de classe, mais n’incluez pas l’implémentation de la fonction. Pour résoudre ce problème, veillez à fournir une définition pour tous les membres de classe que vous appelez.

  • Tentative d’appel d’une fonction virtuelle pure à partir d’une classe de base abstraite. Une fonction virtuelle pure n’a aucune implémentation de classe de base. Pour résoudre ce problème, vérifiez que toutes les fonctions virtuelles appelées sont implémentées.

  • Essayez d’utiliser une variable déclarée dans une fonction (variable locale) en dehors de l’étendue de cette fonction. Pour résoudre ce problème, supprimez la référence à la variable qui n’est pas dans l’étendue, ou déplacez la variable vers une étendue plus élevée.

  • Lorsque vous générez une version Release d’un projet ATL, ce qui génère un message indiquant que le code de démarrage CRT est requis. Pour résoudre ce problème, effectuez l’une des opérations suivantes :

    • Supprimez _ATL_MIN_CRT de la liste des définitions de préprocesseur pour autoriser l’inclusion du code de démarrage CRT. Pour plus d’informations, consultez la page de propriétés générales (Projet).

    • Si possible, supprimez les appels aux fonctions CRT qui nécessitent du code de démarrage CRT. Utilisez plutôt leurs équivalents Win32. Par exemple, utilisez lstrcmp au lieu de strcmp. Les fonctions connues qui nécessitent du code de démarrage CRT sont certaines des fonctions de chaîne et de virgule flottante.

Problèmes de cohérence

Il n’existe actuellement aucune norme pour la décoration de noms C++ entre les fournisseurs du compilateur, ou même entre différentes versions du même compilateur. Les fichiers objet compilés avec différents compilateurs peuvent ne pas utiliser le même schéma de nommage. Les liaisons peuvent entraîner une erreur LNK2001.

La combinaison d’options de compilation inline et non incorporées sur différents modules peut entraîner LNK2001. Si une bibliothèque C++ est créée avec l’incorporation de fonctions activée (/Ob1 ou /Ob2), mais que le fichier d’en-tête correspondant décrivant les fonctions a été désactivé (aucune inline mot clé), cette erreur se produit. Pour résoudre ce problème, définissez les fonctions inline dans le fichier d’en-tête que vous incluez dans d’autres fichiers sources.

Si vous utilisez la directive du #pragma inline_depth compilateur, vérifiez que vous avez défini une valeur de 2 ou supérieure, et vérifiez que vous utilisez également l’option de compilateur /Ob1 ou /Ob2 .

Cette erreur peut se produire si vous omettez l’option LINK /NOENTRY lorsque vous créez une DLL de ressource uniquement. Pour résoudre ce problème, ajoutez l’option /NOENTRY à la commande de lien.

Cette erreur peut se produire si vous utilisez des paramètres /SUBSYSTEM ou /ENTRY incorrects dans votre projet. Par exemple, si vous écrivez une application console et spécifiez /SUBSYSTEM :WINDOWS, une erreur externe non résolue est générée pour WinMain. Pour résoudre ce problème, veillez à faire correspondre les options au type de projet. Pour plus d’informations sur ces options et points d’entrée, consultez les options /SUBSYSTEM et /ENTRY Linker.

Problèmes de symboles de fichier .def exportés

Cette erreur se produit lorsqu’une exportation répertoriée dans un fichier .def est introuvable. Cela peut être dû au fait que l’exportation n’existe pas, est orthographié incorrectement ou utilise des noms décorés C++. Un fichier .def ne prend pas de noms décorés. Pour résoudre ce problème, supprimez les exportations inutiles et utilisez extern "C" des déclarations pour les symboles exportés.

Utilisez le nom décoré pour rechercher l’erreur

Le compilateur C++ et l’éditeur de liens utilisent la décoration de noms, également appelé nom-mangling. La décoration de nom encode des informations supplémentaires sur le type d’une variable dans son nom de symbole. Le nom de symbole d’une fonction encode son type de retour, ses types de paramètres, son étendue et sa convention d’appel. Ce nom décoré est le nom du symbole que l’éditeur de liens recherche pour résoudre les symboles externes.

Une erreur de lien peut se produire si la déclaration d’une fonction ou d’une variable ne correspond pas exactement à la définition de la fonction ou de la variable. C’est parce que toute différence devient une partie du nom du symbole à mettre en correspondance. L’erreur peut se produire même si le même fichier d’en-tête est utilisé à la fois dans le code appelant et dans le code de définition. L’une des manières possibles est que vous compilez les fichiers sources à l’aide de différents indicateurs de compilateur. Par exemple, si votre code est compilé pour utiliser la __vectorcall convention d’appel, mais que vous liez à une bibliothèque qui s’attend à ce que les clients l’appellent à l’aide de la convention par défaut __cdecl ou __fastcall d’appel. Dans ce cas, les symboles ne correspondent pas, car les conventions d’appel sont différentes.

Pour vous aider à trouver la cause, le message d’erreur affiche deux versions du nom. Il affiche à la fois le « nom convivial », le nom utilisé dans le code source et le nom décoré (entre parenthèses). Vous n’avez pas besoin de savoir comment interpréter le nom décoré. Vous pouvez toujours rechercher et comparer avec d’autres noms décorés. Les outils en ligne de commande peuvent vous aider à rechercher et comparer le nom de symbole attendu et le nom du symbole réel :

  • Les options /EXPORTS et /SY Mo OLS de l’outil en ligne de commande DUMPBIN sont utiles ici. Ils peuvent vous aider à découvrir quels symboles sont définis dans vos fichiers .dll et objet ou bibliothèque. Vous pouvez utiliser la liste des symboles pour vérifier que les noms décorés exportés correspondent aux noms décorés que l’éditeur de liens recherche.

  • Dans certains cas, l’éditeur de liens ne peut signaler que le nom décoré d’un symbole. Vous pouvez utiliser l’outil en ligne de commande UNDNAME pour obtenir la forme non décorée d’un nom décoré.

Ressources supplémentaires

Pour plus d’informations, consultez la question Stack Overflow « Qu’est-ce qu’une erreur de symbole externe non définie/non définie et comment puis-je la corriger ? ».