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. Se debe a que la definición puede estar en un archivo o biblioteca de origen diferente. Si se hace referencia a un símbolo pero nunca se define, 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 compilado como C crea nombres decorados para símbolos que son diferentes de los nombres decorados para los mismos símbolos declarados en un archivo de C++, a menos que use un modificador extern "C". 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 ese encabezado en los archivos .cpp. También puede hacer que la variable no sea constante y usar una referencia constante para acceder a ella.

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, es posible que reciba 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 a símbolo externo sin resolver WinMain al que se hace referencia en la función function_name, vincule con /SUBSYSTEM:CONSOLE en lugar de /SUBSYSTEM:WINDOWS. 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).

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 intrínseco AVX2, pero no especifica la opción del compilador /ARCH:AVX2, el compilador da por hecho 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 el intrínseco. 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 todos los archivos se han compilado con la misma /Zc:wchar_t configuración, es posible que las referencias de tipo 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.

Una static biblioteca que se creó con una versión de Visual Studio antes de Visual Studio 2015 podría 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 exportaciones individuales de las funciones insertadas 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 símbolos para las funciones *printf* y *scanf* que están 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 representativos diferentes para los símbolos externos. 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 opciones /EXPORTS y /SYMBOLS de la utilidad DUMPBIN pueden ayudar a averiguar qué símbolos están definidos en el archivo .dll y en los archivos de objeto o biblioteca. Asegúrese de que los nombres representativos exportados coinciden con los nombres representativos que busca el enlazador.

  • La utilidad UNDNAME puede mostrar el símbolo externo no representativo equivalente de un nombre representativo.

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 externas, 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?.