Partilhar via


Erro das ferramentas de vinculador LNK2019

Símbolo external não resolvido 'symbol' referenciado na função 'function'

O código compilado para function faz uma referência ou chamada para symbol, mas o vinculador não consegue localizar a definição de símbolo em nenhuma das bibliotecas ou arquivos de objeto.

Esta mensagem de erro é seguida do erro fatal LNK1120. Para corrigir o erro LNK1120, você deve corrigir todos os erros LNK2001 e LNK2019 primeiro.

Possíveis causas:

Há muitas maneiras de obter esse erro. Todas elas envolvem uma referência a uma função ou variável que o vinculador não pôde resolver ou para a qual ele não pôde encontrar uma definição. O compilador pode identificar quando um símbolo não é declarado, mas não pode informar quando o símbolo não está definido. Isso ocorre porque a definição pode estar em um arquivo ou biblioteca de origem diferente. Se um símbolo for referenciado, mas nunca definido, o vinculador gerará um erro de símbolo external não resolvido.

Estes são alguns problemas comuns que causam o erro LNK2019:

O arquivo de origem que contém a definição do símbolo não foi compilado

No Visual Studio, verifique se o arquivo de origem que define o símbolo foi compilado como parte do projeto. Verifique o diretório de saída de compilação intermediário para obter um arquivo .obj correspondente. Se o arquivo de origem não foi compilado, clique com o botão direito do mouse no arquivo no Gerenciador de Soluções e escolha Propriedades para verificar as propriedades do arquivo. A página Propriedades de Configuração>Geral deve mostrar um Tipo de Item do Compilador C/C++. Na linha de comando, verifique se o arquivo de origem que contém a definição foi compilado.

O arquivo de objeto ou a biblioteca que contém a definição do símbolo não foi vinculado

No Visual Studio, verifique se o arquivo de objeto ou a biblioteca que contém a definição de símbolo foi vinculado como parte do projeto. Na linha de comando, verifique se a lista de arquivos a serem vinculados inclui o arquivo de objeto ou a biblioteca.

A declaração do símbolo não foi escrita da mesma forma que a definição do símbolo

Verifique se você aplicou a ortografia e o uso de maiúsculas corretamente na declaração e na definição e onde quer que o símbolo seja usado ou chamado.

Uma função é usada, mas o tipo ou o número dos parâmetros não corresponde à definição da função

A declaração da função deve corresponder à definição. Verifique se a chamada de função corresponde à declaração e se a declaração corresponde à definição. O código que invoca modelos de função também deve ter declarações de modelo de função correspondentes que incluam os mesmos parâmetros de modelo que a definição. Para obter um exemplo de incompatibilidade de declaração de modelo, confira o LNK2019e.cpp de amostra na seção Exemplos.

Uma função ou variável é declarada, mas não definida

O erro LNK2019 pode ocorrer quando existe uma declaração em um arquivo de cabeçalho, mas nenhuma definição de correspondência é implementada. Para funções de membros ou membros de dados static, a implementação deve incluir o seletor de escopo de classe. Para obter um exemplo, confira Corpo ou Variável de Função Ausente.

A convenção de chamada é diferente entre a declaração da função e a definição da função

Algumas convenções de chamada (__cdecl, __stdcall, __fastcall e __vectorcall) são codificadas como parte do nome decorado. Verifique se a convenção de chamada é a mesma.

Um símbolo é definido em um arquivo do C, mas declarado sem usar extern "C" em um arquivo do C++

Um arquivo compilado como C cria nomes decorados para símbolos que são diferentes dos nomes decorados para os mesmos símbolos declarados em um arquivo do C++, a menos que você use um modificador extern "C". Verifique se a declaração corresponde ao vínculo de compilação para cada símbolo. Da mesma forma, se você definir um símbolo em um arquivo C++ que será usado por um programa C, use extern "C" na definição.

Um símbolo é definido como static e depois referenciado fora do arquivo

No C++, ao contrário do C, global constants têm o vínculo static. Para contornar essa limitação, você pode incluir as inicializações const em um arquivo de cabeçalho e incluir esse cabeçalho nos arquivos .cpp ou gerar a variável não constant e usar uma referência constant para acessá-la.

Um membro static de uma classe não foi definido

Um membro de classe static deve ter uma definição exclusiva ou violará a regra de uma definição. Um membro de classe static que não pode ser definido embutido deve ser definido em um arquivo de origem usando o nome totalmente qualificado. Se não foi definido, o vinculador gerará o erro LNK2019.

Uma dependência de compilação é definida apenas como dependência de projeto na solução

Nas versões anteriores do Visual Studio, esse nível de dependência era suficiente. No entanto, a partir do Visual Studio 2010, o Visual Studio exige uma referência projeto a projeto. Se o seu projeto não tiver uma referência de projeto para projeto, você poderá receber esse erro do vinculador. Adicione uma referência projeto a projeto para corrigi-lo.

Um ponto de entrada não foi definido

O código do aplicativo deve definir um ponto de entrada apropriado: main ou wmain, para aplicativos de console, e WinMain ou wWinMain, para aplicativos do Windows. Para obter mais informações, confira main function and command-line arguments ou WinMain function. Para usar um ponto de entrada personalizado, especifique a opção do vinculador /ENTRY (Símbolo do ponto de entrada).

Você cria um aplicativo de console usando as configurações para um aplicativo do Windows

Se a mensagem de erro for semelhante a unresolved external symbol WinMain referenciado na função function_name, vincule usando /SUBSYSTEM:CONSOLE em vez de /SUBSYSTEM:WINDOWS. Para obter mais informações sobre essa configuração e as instruções sobre como definir essa propriedade no Visual Studio, confira /SUBSYSTEM (Especificar subsistema).

As bibliotecas e os arquivos de objeto vinculados ao código devem ser compilados para a mesma arquitetura que o código. Verifique se as bibliotecas referenciadas pelo projeto são compiladas para a mesma arquitetura que o projeto. Verifique se a propriedade /LIBPATH ou os Diretórios de Biblioteca Adicionais apontam para as bibliotecas criadas para a arquitetura correta.

Você usa diferentes opções do compilador para inlining de função em arquivos de origem diferentes

O uso de funções embutidas definidas em arquivos .cpp e a combinação de opções do compilador embutido de funções em diferentes arquivos de origem pode causar o erro LNK2019. Para obter mais informações, confira Problemas de Inlining de Função.

Você usa variáveis automáticas fora do escopo

As variáveis automáticas (escopo de função) só podem ser usadas no escopo dessa função. Essas variáveis não podem ser declaradas extern e usadas em outros arquivos de origem. Para obter um exemplo, confira Variáveis Automáticas (Escopo da Função).

Você chama funções intrínsecas ou passa tipos de argumento para funções intrínsecas que não têm suporte na arquitetura de destino

Por exemplo, se você usar um intrínseco AVX2, mas não especificar a opção do compilador /ARCH:AVX2, o compilador vai pressupor que o intrínseco seja uma função external. Em vez de gerar uma instrução embutida, o compilador gera uma chamada para um símbolo external com o mesmo nome que o intrínseco. Quando o vinculador tenta localizar a definição dessa função ausente, ele gera o erro LNK2019. Use apenas os intrínsecos e tipos compatíveis com a arquitetura de destino.

Você combina o código que usa wchar_t nativo com código que não usa

O trabalho de conformidade com a linguagem C++ que foi feito no Visual Studio 2005 tornou o wchar_t um tipo nativo por padrão. Se nem todos os arquivos tiverem sido compilados usando as mesmas configurações /Zc:wchar_t, as referências de tipo poderão não ser resolvidas para tipos compatíveis. Verifique se os tipos wchar_t em todos os arquivos de biblioteca e de objeto são compatíveis. Atualize em um typedef wchar_t ou use configurações /Zc:wchar_t consistentes ao compilar.

Uma biblioteca static que foi criada usando uma versão do Visual Studio anterior ao Visual Studio 2015 pode causar erros LNK2019 quando vinculada ao UCRT. Os arquivos de cabeçalho <stdio.h>, <conio.h> e <wchar.h>do UCRT agora definem muitas variações de *printf* e *scanf* como funções inline. As funções embutidas são implementadas por um conjunto menor de funções comuns. As exportações individuais para as funções embutidas não estão disponíveis nas bibliotecas do UCRT padrão, que exportam apenas as funções comuns. Há algumas formas de resolver esse problema. O método que recomendamos é recriar a biblioteca herdada com sua versão atual do Visual Studio. O código da biblioteca deve usar os cabeçalhos padrão para as definições das funções *printf* e *scanf* que causaram os erros. Outra opção para uma biblioteca herdada que você não pode recompilar é adicionar legacy_stdio_definitions.lib à lista de bibliotecas vinculadas. Esse arquivo de biblioteca fornece símbolos para as funções *printf* e *scanf* que estão embutidas nos cabeçalhos do UCRT. Para obter mais informações, confira a seção Bibliotecas em Visão geral de possíveis problemas de atualização.

Problemas de biblioteca de terceiros e vcpkg

Se você vir esse erro ao tentar configurar uma biblioteca de terceiros como parte de seu build, considere usar o vcpkg. O vcpkg é um gerenciador de pacotes do C++ que usa as ferramentas existentes do Visual Studio para instalar e compilar a biblioteca. O vcpkg dá suporte a uma lista de bibliotecas de terceiros grande e crescente. Ele define todas as propriedades e dependências de configuração necessárias para compilações bem-sucedidas como parte do projeto.

Ferramentas de diagnóstico

Às vezes, é difícil explicar o motivo pelo qual o vinculador não consegue encontrar uma definição de símbolo específica. Muitas vezes, o problema é que você não incluiu o código que contém a definição na compilação. Ou, as opções de compilação criaram nomes decorados diferentes para símbolos external. Há várias ferramentas e opções que podem ajudar a diagnosticar erros LNK2019.

  • A opção do vinculador /VERBOSE pode ajudar a determinar quais arquivos são referenciados pelo vinculador. Essa opção pode ajudar a verificar se o arquivo que contém a definição do símbolo foi incluído na compilação.

  • As opções /EXPORTS e /SYMBOLS do utilitário DUMPBIN podem ajudar a descobrir quais símbolos foram definidos nos arquivos .dll e nos arquivos de objeto ou de biblioteca. Verifique se os nomes decorados exportados correspondem aos nomes decorados que o vinculador procura.

  • O utilitário UNDNAME pode mostrar o símbolo externall não decorado equivalente para um nome decorado.

Exemplos

Estes são vários exemplos de código que causam erros LNK2019, juntamente com as informações sobre como corrigir os erros.

Um símbolo foi declarado, mas não definido

Neste exemplo, uma variável external foi declarada, mas não definida:

// 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 é outro exemplo em que uma variável e uma função são declaradas como extern, mas nenhuma definição é fornecida:

// 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 i e g sejam definidos em um dos arquivos incluídos na compilação, o vinculador gerará o erro LNK2019. Você pode corrigir os erros, incluindo o arquivo de código-fonte que contém as definições como parte da compilação. Como alternativa, você pode passar os arquivos .obj ou arquivos .lib que contêm as definições para o vinculador.

Um membro de dados static foi declarado, mas não definido

O erro LNK2019 também pode ocorrer quando um membro de dados static é declarado, mas não definido. A seguinte amostra gera o erro LNK2019 e mostra como corrigi-lo.

// 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;
}

Os parâmetros de declaração não correspondem à definição

O código que invoca modelos de função deve ter declarações de modelo de função correspondentes. As declarações devem incluir os mesmos parâmetros de modelo que a definição. O exemplo a seguir gera o erro LNK2019 em um operador definido pelo usuário e mostra como corrigi-lo.

// 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
}

Definições de tipo wchar_t inconsistentes

Este exemplo cria uma DLL que tem uma exportação que usa WCHAR, a qual é resolvida para o wchar_t.

// LNK2019g.cpp
// compile with: cl /EHsc /LD LNK2019g.cpp
#include "windows.h"
// WCHAR resolves to wchar_t
__declspec(dllexport) void func(WCHAR*) {}

O exemplo a seguir usa a DLL no exemplo anterior e gera o erro LNK2019 porque os tipos unsigned short* e WCHAR* não são os mesmos.

// LNK2019h.cpp
// compile by using: cl /EHsc LNK2019h LNK2019g.lib
// LNK2019 expected
__declspec(dllimport) void func(unsigned short*);

int main() {
   func(0);
}

Para corrigir esse erro, altere unsigned short para wchar_t ou WCHAR, ou compile o LNK2019g.cpp usando /Zc:wchar_t-.

Confira também

Para obter mais informações sobre possíveis causas e soluções para os erros LNK2019, LNK2001 e LNK1120, confira a pergunta no Stack Overflow: What is an undefined reference/unresolved external symbol error and how do I fix it?.