Erreur des outils Éditeur de liens LNK2019
symbole externe non résolu 'symbole' référencé dans la fonction 'function'
Le code compilé pour fonction effectue une référence ou un appel à symbole, mais l’éditeur de liens ne parvient pas à trouver la définition de symbole dans les bibliothèques ou les fichiers objets.
Ce message d’erreur est suivi de l’erreur irrécupérable LNK1120. Pour corriger l’erreur LNK1120, vous devez d’abord corriger toutes les erreurs LNK2001 et LNK2019.
Causes possibles
Il existe de nombreuses façons d’obtenir cette erreur. Toutes impliquent une référence à une fonction ou une variable que l’éditeur de liens n’a pas pu résoudre, ou pour laquelle il n’est pas parvenu à trouver de définition. Le compilateur peut identifier le moment où un symbole n’est pas déclaré, mais il ne peut pas dire quand le symbole n’est pas défini. En effet, la définition peut se trouver dans un autre fichier source ou une autre bibliothèque. Si un symbole est référencé mais jamais défini, l’éditeur de liens génère une erreur de symbole externe non résolue.
Voici un aperçu des problèmes courants qui provoquent l'erreur LNK2019 :
Le fichier source qui contient la définition du symbole n’est pas compilé
Dans Visual Studio, vérifiez que le fichier source qui définit le symbole est compilé dans le cadre de votre projet. Recherchez dans le répertoire de sortie de build intermédiaire un fichier.obj correspondant. Si le fichier source n’est pas compilé, cliquez avec le bouton droit sur celui-ci dans l’Explorateur de solutions, puis choisissez Propriétés pour vérifier les propriétés du fichier. La page Propriétés de configuration>Général doit afficher un Type d’élément du Compilateur C/C++. Sur la ligne de commande, vérifiez que le fichier source qui contient la définition est compilé.
Le fichier objet ou la bibliothèque qui contient la définition du symbole n’est pas lié
Dans Visual Studio, vérifiez que le fichier objet ou la bibliothèque qui contient la définition de symbole est lié dans le cadre de votre projet. Sur la ligne de commande, vérifiez que la liste des fichiers à lier inclut le fichier objet ou la bibliothèque.
La déclaration du symbole n’est pas orthographiée de la même manière que la définition du symbole
Vérifiez que vous utilisez l’orthographe et la mise en majuscules appropriées dans la déclaration et la définition, et partout où le symbole est utilisé ou appelé.
Une fonction est utilisée, mais le type ou le nombre de paramètres ne correspond pas à la définition de la fonction
La déclaration de la fonction doit correspondre à la définition. Vérifiez que l’appel de fonction correspond à la déclaration, et que la déclaration correspond à la définition. Le code qui appelle des modèles de fonction doit également comporter des déclarations de modèles de fonction correspondantes, qui incluent les mêmes paramètres de modèle que la définition. Pour obtenir un exemple de déclaration de modèle non conforme, consultez l’exemple LNK2019e.cpp dans la section Exemples.
Une fonction ou une variable est déclarée mais pas définie
L’erreur LNK2019 peut se produire quand une déclaration existe dans un fichier d’en-tête, mais qu’aucune définition correspondante n’est implémentée. Pour les fonctions membres ou les membres de données static, l’implémentation doit inclure le sélecteur d’étendue de classe. Pour obtenir un exemple, consultez Missing Function Body or Variable.
La convention d’appel est différente entre la déclaration de fonction et la définition de fonction
Certaines conventions d’appel (__cdecl
, __stdcall
, __fastcall
et __vectorcall
) sont codées dans le cadre du nom décoré. Vérifiez que la convention d’appel est la même.
Un symbole est défini dans un fichier C, mais déclaré sans utiliser extern "C"
dans un fichier C++
Un fichier compilé en C crée des noms symbols décorés pour ceux qui sont différents des noms décorés pour le même symbols fichier déclaré dans un fichier C++, sauf si vous utilisez un extern "C"
modificateur. Vérifiez que la déclaration correspond à la liaison de compilation pour chaque symbole. De même, si vous définissez un symbole dans un fichier C++ qui sera utilisé par un programme C, utilisez extern "C"
dans la définition.
Un symbole est défini en tant que static, puis référencé plus tard en dehors du fichier
En C++, contrairement à C, les constantes globales ont une liaison static
. Pour contourner cette limitation, vous pouvez inclure les initialisations const
dans un fichier d'en-tête et inclure cet en-tête dans vos fichiers .cpp. Vous pouvez aussi rendre la variable non constante et utiliser une référence constante pour y accéder.
Un membre static d’une classe n’est pas défini
Un membre de classe static doit avoir une définition unique, sinon il enfreint la règle de définition unique. Un membre de classe static qui ne peut pas être défini inline doit l’être dans un fichier source à l’aide de son nom complet. S’il n’est pas défini du tout, l’éditeur de liens génère l’erreur LNK2019.
Une dépendance de build est uniquement définie en tant que dépendance de projet dans la solution
Dans les versions antérieures de Visual Studio, ce niveau de dépendance était suffisant. Toutefois, à partir de Visual Studio 2010, Visual Studio nécessite une référence de projet à projet. Si votre projet n’a pas de référence de projet à projet, vous risquez de recevoir cette erreur de l’éditeur de liens. Ajoutez une référence entre projets pour corriger ce problème.
Un point d’entrée n’est pas défini
Le code de l’application doit définir un point d’entrée approprié : main
ou wmain
pour les applications console, et WinMain
ou wWinMain
pour les applications Windows. Pour plus d’informations, consultez Fonction main
et arguments de ligne de commande ou WinMain
, fonction. Pour utiliser un point d’entrée personnalisé, spécifiez l’option d’éditeur de liens /ENTRY
(symbole de point d’entrée).
Vous générez une application console en utilisant les paramètres d’une application Windows
Si le message d’erreur est similaire au symbole externe non résolu référencé dans la fonction function_name, liez à l’aide /SUBSYSTEM:CONSOLE
au lieu de /SUBSYSTEM:WINDOWS
WinMain . Pour plus d’informations sur ce paramètre, et pour obtenir des instructions sur la définition de cette propriété dans Visual Studio, consultez /SUBSYSTEM
(spécifier le sous-système).
Vous tentez de lier des bibliothèques 64 bits à du code 32 bits, ou des bibliothèques 32 bits à du code 64 bits
Les bibliothèques et les fichiers objets liés à votre code doivent être compilés pour la même architecture que votre code. Vérifiez que les bibliothèques référencées par votre projet sont compilées pour la même architecture que votre projet. Vérifiez que la propriété /LIBPATH
ou Répertoires de bibliothèques supplémentaires pointe vers les bibliothèques générées pour l’architecture appropriée.
Vous utilisez différentes options de compilateur pour l’incorporation de fonctions inline dans différents fichiers sources
L’utilisation de fonctions inline définies dans des fichiers .cpp et le panachage d’options de compilateur pour incorporer des fonctions inline dans différents fichiers sources peut occasionner l’erreur LNK2019. Pour plus d'informations, consultez Function Inlining Problems.
Vous utilisez des variables automatiques en dehors de leur étendue
Les variables automatiques (portée de fonction) ne peuvent être utilisées que dans la portée de la fonction en question. Ces variables ne peuvent pas être déclarées comme étant extern
et utilisées dans d’autres fichiers sources. Pour obtenir un exemple, consultez Automatic (Function Scope) Variables.
Vous appelez des fonctions intrinsèques, ou passez des types d’arguments à des fonctions intrinsèques qui ne sont pas prises en charge par votre architecture cible
Par exemple, si vous utilisez une AVX2 intrinsèque, mais que vous ne spécifiez pas l’option /ARCH:AVX2
du compilateur, le compilateur suppose que l’intrinsèque est une fonction externe. Au lieu de générer une instruction inline, le compilateur génère un appel à un symbole externe avec le même nom que la fonction intrinsèque. Quand l'éditeur de liens tente de trouver la définition de cette fonction manquante, il génère l'erreur LNK2019. Veillez à utiliser uniquement les intrinsèques et des types pris en charge par votre architecture cible.
Vous mélangez du code qui utilise le type wchar_t
natif avec du code qui ne l’utilise pas
Le travail de mise en conformité du langage C++ effectué dans Visual Studio 2005 a fait de wchar_t
un type natif par défaut. Si tous les fichiers n’ont pas été compilés à l’aide des mêmes paramètres /Zc:wchar_t
, les références de type risquent de ne pas être résolues en types compatibles. Vérifiez que les types wchar_t
de tous les fichiers bibliothèques et fichiers objets sont compatibles. Effectuez une mise à jour à partir d’un typedef wchar_t
, ou utilisez des paramètres /Zc:wchar_t cohérents quand vous compilez.
Vous obtenez des erreurs pour les fonctions *printf*
et *scanf*
quand vous liez une bibliothèque static héritée
Une bibliothèque static générée à l’aide d’une version de Visual Studio antérieure à Visual Studio 2015 peut provoquer des erreurs LNK2019 quand elle est liée à l’UCRT. Les fichiers d’en-tête UCRT <stdio.h>
, <conio.h>
et <wchar.h>
définissent désormais de nombreuses variantes de *printf*
et *scanf*
en tant que fonctions inline
. Les fonctions inlined sont implémentées par un ensemble plus restreint de fonctions usuelles. Les exports fonctions inline ne sont pas disponibles dans les bibliothèques UCRT standard, qui exportent uniquement les fonctions courantes. Il existe plusieurs façons de résoudre ce problème. La méthode que nous recommandons consiste à regénérer la bibliothèque héritée avec votre version actuelle de Visual Studio. Vérifiez que le code de la bibliothèque utilise les en-têtes standard pour les définitions des fonctions *printf*
et *scanf*
à l’origine des erreurs. Il existe une autre option pour une bibliothèque héritée que vous ne pouvez pas regénérer. Elle consiste à ajouter legacy_stdio_definitions.lib
à la liste des bibliothèques que vous liez. Ce fichier de bibliothèque fournit symbols les *printf*
*scanf*
fonctions incluses dans les en-têtes UCRT. Pour plus d’informations, consultez la section Bibliothèques dans Vue d’ensemble des problèmes de mise à niveau potentiels.
Problèmes liés aux bibliothèques tierces et vcpkg
Si vous voyez cette erreur quand vous essayez de configurer une bibliothèque tierce dans le cadre de votre build, utilisez vcpkg. vcpkg est un gestionnaire de package C++ qui utilise vos outils Visual Studio existants pour installer et générer la bibliothèque. vcpkg prend en charge une liste de bibliothèques tierces toujours plus importante. Il définit l’ensemble des propriétés et dépendances de configuration nécessaires à la réussite des builds dans le cadre de votre projet.
Outils de diagnostic
Il est parfois difficile de déterminer la raison pour laquelle l’éditeur de liens ne parvient pas à trouver une définition de symbole particulière. Le problème vient souvent du fait que vous n’avez pas inclus le code contenant la définition dans votre build. Ou, les options de génération ont créé différents noms décorés pour des noms externes symbols. Il existe plusieurs outils et options qui peuvent vous aider à diagnostiquer les erreurs LNK2019.
L’option d’éditeur de liens
/VERBOSE
peut vous aider à identifier les fichiers référencés par l’éditeur de liens. Cette option peut vous aider à vérifier si le fichier qui contient la définition du symbole est inclus dans votre build.Les
/EXPORTS
options de/SYMBOLS
l’utilitaire DUMPBIN peuvent vous aider à découvrir les symbols paramètres définis dans vos fichiers .dll et objet ou bibliothèque. Vérifiez que les noms décorés exportés correspondent aux noms décorés recherchés par l’éditeur de liens.L’utilitaire UNDNAME peut vous montrer le symbole externe non décoré équivalent pour un nom décoré.
Exemples
Voici plusieurs exemples de code à l’origine des erreurs LNK2019 ainsi que des informations sur la façon de corriger ces erreurs.
Un symbole est déclaré mais pas défini
Dans cet exemple, une variable externe est déclarée, mais non définie :
// 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
}
Voici un autre exemple où une variable et une fonction sont déclarées en tant que extern
mais aucune définition n’est fournie :
// LNK2019c.cpp
// Compile by using: cl /EHsc LNK2019c.cpp
// LNK2019 expected
extern int i;
extern void g();
void f() {
i++;
g();
}
int main() {}
À moins que i
et g
ne soient définis dans l’un des fichiers inclus dans la build, l’éditeur de liens génère l’erreur LNK2019. Vous pouvez corriger les erreurs en incluant le fichier de code source qui contient les définitions dans le cadre de la compilation. Vous pouvez également passer les fichiers .obj
ou .lib
qui contiennent les définitions à l’éditeur de liens.
Un membre de données static est déclaré mais pas défini
L’erreur LNK2019 peut également se produire quand un membre de données static est déclaré mais non défini. L'exemple suivant génère l'erreur LNK2019 et montre comment la corriger.
// 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;
}
Les paramètres de déclaration ne correspondent pas à la définition
Le code qui appelle des modèles de fonction doit avoir des déclarations de modèle de fonction correspondantes. Les déclarations doivent inclure les mêmes paramètres de modèle que la définition. L'exemple suivant génère l'erreur LNK2019 sur un opérateur défini par l'utilisateur et montre comment la corriger.
// 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
}
Définitions de types wchar_t incohérentes
Cet exemple crée une DLL dont l’exportation utilise WCHAR
, qui se résout en wchar_t
.
// LNK2019g.cpp
// compile with: cl /EHsc /LD LNK2019g.cpp
#include "windows.h"
// WCHAR resolves to wchar_t
__declspec(dllexport) void func(WCHAR*) {}
L’exemple suivant utilise la DLL de l’exemple précédent, et génère l’erreur LNK2019, car les types unsigned short*
et WCHAR*
ne sont pas les mêmes.
// LNK2019h.cpp
// compile by using: cl /EHsc LNK2019h LNK2019g.lib
// LNK2019 expected
__declspec(dllimport) void func(unsigned short*);
int main() {
func(0);
}
Pour corriger cette erreur, remplacez unsigned short
par wchar_t
ou WCHAR
, ou compilez LNK2019g.cpp à l’aide de /Zc:wchar_t-
.
Voir aussi
Pour plus d’informations sur les causes possibles et les solutions des erreurs LNK2019, LNK2001 et LNK1120, consultez la question Stack Overflow : What is an undefined reference/unresolved external symbol error and how do I fix it?
.