Error de las herramientas del vinculador LNK2019
símbolo externo sin resolver 'symbol' al que se hace referencia en la función 'function'
El código compilado de function hace una referencia o llama a symbol, pero el enlazador no puede encontrar la definición de symbol en ninguno de los archivos de objeto o biblioteca.
A este mensaje de error le sigue el error irrecuperable LNK1120. Para corregir el error LNK1120, primero debe corregir todos los errores LNK2001 y LNK2019.
Causas posibles:
Hay muchas maneras de que aparezca este error. Todas ellas implican una referencia a una función o variable que el enlazador no pudo resolver o para la que no pudo encontrar una definición. El compilador puede identificar cuándo no se declara un símbolo, pero no puede saber cuándo no está definido. Esto se debe a que la definición puede estar en un archivo de origen o una biblioteca diferente. Si se hace referencia a un símbolo pero nunca definido, el enlazador genera un error de símbolo externo sin resolver.
Estos son algunos de los problemas comunes que causan LNK2019:
El archivo de origen que contiene la definición del símbolo no se compila
En Visual Studio, asegúrese de que el archivo de origen que define el símbolo se compila como parte del proyecto. Compruebe el directorio de salida de compilación intermedio para obtener un archivo .obj coincidente. Si el archivo de origen no está compilado, haga clic con el botón derecho en el archivo en el Explorador de soluciones y seleccione Propiedades para comprobar las propiedades del archivo. La página Propiedades de configuración>General debe mostrar un Tipo de elemento de Compilador de C/C++. En la línea de comandos, asegúrese de que el archivo de origen que contiene la definición está compilado.
El archivo de objeto o biblioteca que contiene la definición del símbolo no está vinculado
En Visual Studio, asegúrese de que el archivo de objeto o biblioteca que contiene la definición del símbolo esté vinculado como parte del proyecto. En la línea de comandos, asegúrese de que la lista de archivos que se van a vincular incluye el archivo de objeto o biblioteca.
La declaración del símbolo no se escribe igual que la definición del símbolo
Compruebe que usa la ortografía y la mayúsculas correctas tanto en la declaración como en la definición, y dondequiera que se use el símbolo o se le llame.
Se usa una función, pero el tipo o número de los parámetros no coincide con su definición
. La declaración de función debe coincidir con su definición. Asegúrese de que la llamada de función coincide con la declaración, y de que la declaración coincide con la definición. El código que invoca plantillas de función también debe tener declaraciones de plantilla de función coincidentes que incluyan los mismos parámetros de plantilla que la definición. Para obtener un ejemplo de un error de coincidencia de declaración de plantilla, vea el ejemplo LNK2019e.cpp en la sección Ejemplos.
Hay una función o variable declarada, pero no definida
LNK2019 puede producirse cuando existe una declaración en un archivo de encabezado, pero no se implementa ninguna definición coincidente. En las funciones miembro o los miembros de datos static, la implementación debe incluir el selector de ámbito de clase. Para obtener un ejemplo, consulta Missing Function Body or Variable.
La convención de llamada es diferente entre la declaración de función y la definición de función
Algunas convenciones de llamada (__cdecl
, __stdcall
, __fastcall
y __vectorcall
) se cifran como parte del nombre representativo. Asegúrese de que la convención de llamada sea igual.
Hay un símbolo definido en un archivo de C, pero se ha declarado sin usar extern "C"
en un archivo de C++
Un archivo que se compila como C crea nombres decorados para symbols los que son diferentes de los nombres decorados para el mismo symbols declarado en un archivo de C++, a menos que use un extern "C"
modificador. Asegúrese de que la declaración coincide con la vinculación de compilación de cada símbolo. Del mismo modo, si define un símbolo en un archivo C++ que se usará en un programa C, use extern "C"
en la definición.
Un símbolo se ha definido como static y luego se ha hecho referencia a él fuera del archivo
. En C++, a diferencia de C, las constantes globales tienen vinculación static
. Para solucionar esta limitación, puede incluir las inicializaciones const
en un encabezado de archivo e incluir dicho encabezado en los archivos .cpp. También puede hacer que la variable no sea constante y usar una referencia constante para obtener acceso.
No hay un miembro static de una clase definido
Un miembro de clase static debe tener una definición única. En caso contrario, infringe la regla de una definición. Un miembro de clase static que no se puede definir insertado debe definirse en un archivo de origen mediante su nombre completo. Si no se define, el enlazador genera LNK2019.
Una dependencia de compilación solo se define como dependencia de proyecto en la solución
En versiones anteriores de Visual Studio, este nivel de dependencia era suficiente. Pero a partir de Visual Studio 2010, Visual Studio requiere una referencia de proyecto a proyecto. Si el proyecto no tiene una referencia de proyecto a proyecto, puede aparecer este error del enlazador. Agregue una referencia de proyecto a proyecto para corregir este problema.
No hay un punto de entrada definido
El código de la aplicación debe definir un punto de entrada adecuado: main
o wmain
para aplicaciones de consola y WinMain
o wWinMain
para aplicaciones Windows. Para obtener más información, vea Función main
y argumentos de la línea de comandos o WinMain
(función). Para usar un punto de entrada personalizado, especifique la opción del enlazador /ENTRY
(Símbolo de punto de entrada).
Se compila una aplicación de consola mediante la configuración de una aplicación Windows
Si el mensaje de error es similar al símbolo externo sin resolver al que se hace referencia en la función function_name, vincule mediante /SUBSYSTEM:CONSOLE
en lugar de /SUBSYSTEM:WINDOWS
WinMain . Para obtener más información acerca de esta configuración y para obtener instrucciones sobre cómo establecer esta propiedad en Visual Studio, consulte /SUBSYSTEM
(Specify Subsystem).
Intenta vincular bibliotecas de 64 bits a código de 32 bits o bibliotecas de 32 bits a código de 64 bits
Los archivos de objeto y biblioteca vinculados al código deben compilarse en la misma arquitectura que el código. Asegúrese de que las bibliotecas a las que hace referencia el proyecto se compilan en la misma arquitectura que el proyecto. Asegúrese de que la propiedad /LIBPATH
o Directorios de bibliotecas adicionales apunta a bibliotecas compiladas en la arquitectura correcta.
Usa opciones del compilador diferentes para la inserción de funciones en distintos archivos de origen
. El uso de funciones insertadas definidas en los archivos .cpp y la mezcla de opciones de compilador de inserción de funciones en archivos de origen diferentes puede causar LNK2019. Para obtener más información, consulta Function Inlining Problems.
Usa variables automáticas fuera de su ámbito
. Las variables automáticas (de ámbito de función) solo pueden usarse dentro del ámbito de esa función. Estas variables no se pueden declarar extern
y usar en otros archivos de origen. Para obtener un ejemplo, consulta Automatic (Function Scope) Variables.
Llama a funciones intrínsecas o pasa tipos de argumentos a funciones intrínsecas que no son compatibles con la arquitectura de destino
Por ejemplo, si usa un AVX2 intrínseco, pero no especifica la /ARCH:AVX2
opción del compilador, el compilador asume que el intrínseco es una función externa. En lugar de generar una instrucción insertada, el compilador genera una llamada a un símbolo externo con el mismo nombre que la función intrínseca. Cuando el enlazador intenta buscar la definición de esta función ausente, genera LNK2019. Asegúrese de que solo usa los intrínsecos y los tipos compatibles con la arquitectura de destino.
Mezcla código que usa wchar_t
nativo con código que no
El trabajo de conformidad del lenguaje C++ realizado en Visual Studio 2005 convirtió wchar_t
en un tipo nativo de manera predeterminada. Si no se compilaron todos los archivos con la misma configuración /Zc:wchar_t
, puede que los tipos de referencia no se resuelvan en tipos compatibles. Asegúrese de que los tipos wchar_t
de todos los archivos de objeto y biblioteca son compatibles. Actualice desde un objeto typedef wchar_t
o use una configuración /Zc:wchar_t coherente al compilar.
Obtiene errores para las funciones *printf*
y *scanf*
al vincular una biblioteca static heredada
Una biblioteca static compilada con una versión de Visual Studio anterior a Visual Studio 2015 puede provocar errores LNK2019 cuando se vincula con UCRT. Los archivos de encabezado UCRT <stdio.h>
, <conio.h>
y <wchar.h>
ahora definen muchas variaciones *printf*
y *scanf*
como funciones inline
. Las funciones insertadas se implementan mediante un conjunto más pequeño de funciones comunes. Las exports funciones insertadas individuales no están disponibles en las bibliotecas UCRT estándar, que solo exportan las funciones comunes. Hay varias maneras de resolver este problema. El método que se recomienda es recompilar la biblioteca heredada con la versión actual de Visual Studio. Asegúrese de que el código de biblioteca usa los encabezados estándar para las definiciones de las funciones *printf*
y *scanf*
que provocaron los errores. Otra opción para una biblioteca heredada que no se puede recompilar es agregar legacy_stdio_definitions.lib
a la lista de bibliotecas vinculadas. Este archivo de biblioteca proporciona symbols las *printf*
funciones y *scanf*
insertadas en los encabezados UCRT. Para obtener más información, consulte la sección Bibliotecas en Información general sobre posibles problemas de actualización.
Problemas de bibliotecas de terceros y vcpkg
Si ve este error al intentar configurar una biblioteca de terceros como parte de la compilación, considere la posibilidad de usar vcpkg. vcpkg es un administrador de paquetes de C++ que usa las herramientas de Visual Studio existentes para instalar y compilar la biblioteca. vcpkg admite una larga lista de bibliotecas de terceros que sigue aumentando. Establece todas las propiedades de configuración y las dependencias necesarias para lograr unas compilaciones correctas como parte del proyecto.
Herramientas de diagnóstico
A veces es difícil saber por qué el enlazador no puede encontrar una definición de símbolo determinada. A menudo, el problema es que no se ha incluido el código que contiene la definición en la compilación. O bien, las opciones de compilación han creado nombres decorados diferentes para el externo symbols. Hay varias herramientas y opciones que pueden ayudar a diagnosticar errores LNK2019.
La opción del enlazador
/VERBOSE
puede ayudar a determinar los archivos a los que hace referencia el enlazador. Esta opción puede ayudar a comprobar si el archivo que contiene la definición del símbolo está incluido en la compilación.Las
/EXPORTS
opciones y/SYMBOLS
de la DUMPBIN utilidad pueden ayudarle a detectar cuáles symbols se definen en los archivos de .dll y de objeto o biblioteca. Asegúrese de que los nombres representativos exportados coinciden con los nombres representativos que busca el enlazador.La UNDNAME utilidad puede mostrar el símbolo externo equivalente sin codificar para un nombre decorado.
Ejemplos
Aquí hay varios ejemplos de código que causan errores LNK2019 junto con información acerca de cómo corregirlos.
Se declaró un símbolo pero no se definió
En este ejemplo, se declara una variable externa, pero no se define:
// 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
}
Este es otro ejemplo en el que se declaran una variable y una función como extern
as, pero no se proporciona ninguna definición:
// LNK2019c.cpp
// Compile by using: cl /EHsc LNK2019c.cpp
// LNK2019 expected
extern int i;
extern void g();
void f() {
i++;
g();
}
int main() {}
A menos que se definan i
y g
en uno de los archivos incluidos en la compilación, el enlazador genera LNK2019. Puede corregir los errores mediante la inclusión del archivo de código fuente que contiene las definiciones como parte de la compilación. Como alternativa, puede pasar archivos .obj
o .lib
que contienen las definiciones al enlazador.
Se declara un miembro de datos static, pero no se define
LNK2019 también puede producirse cuando se declara un miembro de datos static, pero no se define. La muestra siguiente genera LNK2019 y muestra cómo corregirlo.
// 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;
}
Los parámetros de declaración no coinciden con la definición
El código que invoca plantillas de función debe tener declaraciones de plantilla de función coincidentes. Las declaraciones deben incluir los mismos parámetros de plantilla que la definición. La muestra siguiente genera LNK2019 en un operador definido por el usuario y muestra cómo corregirlo.
// 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
}
Definiciones de tipo wchar_t incoherentes
En este ejemplo se crea un archivo DLL que tiene una exportación que usa WCHAR
, que se resuelve 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*) {}
En el ejemplo siguiente se usa el archivo DLL del ejemplo anterior y se genera LNK2019 porque los tipos unsigned short*
y WCHAR*
no son iguales.
// LNK2019h.cpp
// compile by using: cl /EHsc LNK2019h LNK2019g.lib
// LNK2019 expected
__declspec(dllimport) void func(unsigned short*);
int main() {
func(0);
}
Para resolver este error, cambie unsigned short
a wchar_t
o WCHAR
, o bien compile LNK2019g.cpp con /Zc:wchar_t-
.
Consulte también
Para obtener más información sobre las posibles causas y soluciones de los errores LNK2019, LNK2001 y LNK1120, consulte la pregunta de Stack Overflow: What is an undefined reference/unresolved external symbol error and how do I fix it?
.