Partilhar via


Erro de ferramentas de vinculação LNK2001

símbolo externo não resolvido "símbolo"

Observações

O código compilado faz uma referência ou chamada para símbolo. O símbolo não é definido em nenhuma biblioteca ou arquivo de objeto pesquisado pelo vinculador.

Esta mensagem de erro é seguida por erro fatal LNK1120. Para corrigir erros LNK1120, primeiro corrija todos os erros LNK2001 e LNK2019.

Há muitas maneiras de obter erros LNK2001. Todos eles envolvem uma referência a uma função ou variável que o vinculador não consegue resolver ou encontrar uma definição. O compilador pode identificar quando seu código não declara um símbolo, mas não quando não define um. Isso porque a definição pode estar em um arquivo ou biblioteca de origem diferente. Se o seu código se refere a um símbolo, mas nunca é definido, o vinculador gera um erro.

O que é um símbolo externo não resolvido?

Um símbolo é o nome interno de uma função ou variável global. É a forma do nome usado ou definido em um arquivo de objeto compilado ou biblioteca. Uma variável global é definida no arquivo de objeto onde o armazenamento é alocado para ela. Uma função é definida no arquivo de objeto onde o código compilado para o corpo da função é colocado. Um símbolo externo é aquele referenciado em um arquivo de objeto, mas definido em uma biblioteca ou arquivo de objeto diferente. Um símbolo exportado é aquele que é disponibilizado publicamente pelo arquivo de objeto ou biblioteca que o define.

Para criar um aplicativo ou DLL, cada símbolo usado deve ter uma definição. O vinculador deve resolver ou encontrar a definição correspondente para cada símbolo externo referenciado por cada arquivo de objeto. O vinculador gera um erro quando não consegue resolver um símbolo externo. Isso significa que o vinculador não conseguiu encontrar uma definição de símbolo exportado correspondente em nenhum dos arquivos vinculados.

Este erro pode ocorrer:

  • Quando o projeto tem uma referência em falta a um ficheiro de biblioteca (.LIB) ou de objeto (.OBJ). Para corrigir esse problema, adicione uma referência à biblioteca necessária ou arquivo de objeto para o seu projeto. Para obter mais informações, consulte lib Files como entrada do vinculador.

  • Quando o projeto tem uma referência a uma biblioteca (. LIB) ou objeto (. OBJ) que, por sua vez, requer símbolos de outra biblioteca. Isso pode acontecer mesmo se você não chamar funções que causam a dependência. Para corrigir esse problema, adicione uma referência à outra biblioteca ao seu projeto. Para obter mais informações, consulte Compreender o modelo clássico de ligação: Integrando símbolos ao processo.

  • Se você usar as opções /NODEFAULTLIB ou /Zl . Quando você especifica essas opções, as bibliotecas que contêm o código necessário não são vinculadas ao projeto, a menos que você as tenha incluído explicitamente. Para corrigir esse problema, inclua explicitamente todas as bibliotecas que você usa na linha de comando do link. Se vir muitos nomes de funções CRT ou da biblioteca padrão ausentes ao usar estas opções, inclua explicitamente as DLLs da CRT e da biblioteca padrão ou os arquivos de biblioteca no link.

  • Se você compilar usando a opção /clr . Pode faltar uma referência a .cctor. Para obter mais informações sobre como corrigir esse problema, consulte Inicialização de assemblies mistos.

  • Se você vincular às bibliotecas do modo de liberação ao criar uma versão de depuração de um aplicativo. Da mesma forma, se você usar as opções /MTd ou /MDd ou definir _DEBUG e, em seguida, vincular às bibliotecas de versão, você deve esperar muitos potenciais externos não resolvidos, entre outros problemas. Ligar uma compilação em modo de release com as bibliotecas de depuração também causa problemas semelhantes. Para corrigir esse problema, certifique-se de usar as bibliotecas de depuração em compilações de depuração e bibliotecas de distribuição em compilações de distribuição.

  • Se o seu código se refere a um símbolo de uma versão da biblioteca, mas você vincula uma versão diferente da biblioteca. Geralmente, não é possível misturar arquivos de objeto ou bibliotecas criadas para diferentes versões do compilador. As bibliotecas fornecidas em uma versão podem conter símbolos que não podem ser encontrados nas bibliotecas incluídas com outras versões. Para corrigir esse problema, crie todos os arquivos de objeto e bibliotecas com a mesma versão do compilador antes de vinculá-los. Para obter mais informações, consulte Compatibilidade binária C++ entre versões do Visual Studio.

  • Se os caminhos da biblioteca estiverem desatualizados. A caixa de diálogo Opções de > Ferramentas > Projetos > Diretórios VC++, na seleção Arquivos de biblioteca, permite alterar a ordem de pesquisa da biblioteca. A pasta Linker na caixa de diálogo Propriedades do Projeto também pode conter caminhos que podem estar desatualizados.

  • Quando um novo SDK do Windows é instalado (talvez em um local diferente). A ordem de pesquisa da biblioteca deve ser atualizada para apontar para o novo local. Normalmente, você deve colocar o caminho para novos diretórios SDK include e lib na frente do local padrão do Visual C++. Além disso, um projeto contendo caminhos incorporados ainda pode apontar para caminhos antigos que são válidos, mas desatualizados. Atualize os caminhos para a nova funcionalidade adicionada pela versão mais recente instalada num local diferente.

  • Se você compilar na linha de comando e tiver criado suas próprias variáveis de ambiente. Verifique se os caminhos para ferramentas, bibliotecas e arquivos de cabeçalho vão para uma versão consistente. Para obter mais informações, consulte Usar o conjunto de ferramentas MSVC a partir da linha de comando.

Problemas de codificação

Este erro pode ser causado por:

  • Caso incompatível em seu código-fonte ou arquivo de definição de módulo (.def). Por exemplo, se você nomear uma variável var1 em um arquivo de origem C++ e tentar acessá-la como VAR1 em outro, esse erro será gerado. Para corrigir esse problema, use nomes consistentemente escritos e com maiúsculas.

  • Um projeto que usa inlining de função. Isso pode ocorrer quando você define as funções como inline em um arquivo de origem, em vez de em um arquivo de cabeçalho. As funções embutidas não podem ser vistas fora do arquivo de origem que as define. Para corrigir esse problema, defina as funções embutidas nos cabeçalhos onde elas são declaradas.

  • Chamar uma função C de um programa C++ sem usar uma extern "C" declaração para a função C. O compilador usa diferentes convenções de nomenclatura de símbolos internos para código C e C++. O nome do símbolo interno é o que o vinculador procura ao resolver símbolos. Para corrigir esse problema, use um extern "C" wrapper em torno de todas as declarações de funções C usadas em seu código C++, o que faz com que o compilador use a convenção de nomenclatura interna C para esses símbolos. As opções do compilador /Tp e /Tc fazem com que o compilador compile arquivos como C++ ou C, respectivamente, independentemente da extensão do nome do arquivo. Essas opções podem causar nomes de funções internas diferentes do esperado.

  • Uma tentativa de fazer referência a funções ou dados que não têm ligação externa. Em C++, funções inline e const dados têm ligação interna, a menos que explicitamente especificado como extern. Para corrigir esse problema, use declarações explícitas extern em símbolos referidos fora do arquivo de origem definidor.

  • Um corpo de função ausente ou definição de variável . Esse erro é comum quando você declara, mas não define, variáveis, funções ou classes em seu código. O compilador só precisa de um protótipo de função ou extern declaração de variável para gerar um arquivo de objeto sem erro, mas o vinculador não pode resolver uma chamada para a função ou uma referência para a variável porque não há código de função ou espaço de variável reservado. Para corrigir esse problema, certifique-se de definir cada função referenciada e variável em um arquivo de origem ou biblioteca vinculada.

  • Uma chamada de função que usa tipos de retorno e parâmetro ou convenções de chamada que não correspondem às da definição de função. Em arquivos de objeto C++, a decoração de nome codifica a convenção de chamada, a classe ou o escopo do namespace e os tipos de retorno e parâmetro de uma função. A cadeia de caracteres codificada torna-se parte do nome final da função decorada. Esse nome é usado pelo vinculador para resolver, ou corresponder, chamadas para a função de outros arquivos de objeto. Para corrigir esse problema, verifique se a declaração de função, a definição e as chamadas usam os mesmos escopos, tipos e convenções de chamada.

  • Código C++ que você chama, quando você inclui um protótipo de função em uma definição de classe, mas não inclui a implementação da função. Para corrigir esse problema, certifique-se de fornecer uma definição para todos os membros da classe que você chama.

  • Uma tentativa de chamar uma função virtual pura a partir de uma classe base abstrata. Uma função virtual pura não tem implementação de classe base. Para corrigir esse problema, certifique-se de que todas as funções virtuais chamadas são implementadas.

  • Tentar usar uma variável declarada dentro de uma função (uma variável local) fora do escopo dessa função. Para corrigir esse problema, remova a referência à variável que não está no escopo ou mova a variável para um escopo mais alto.

  • Quando se compila uma versão Release de um projeto ATL, é produzida uma mensagem de que o código de inicialização CRT é necessário. Para corrigir esse problema, siga um destes procedimentos,

    • Remover _ATL_MIN_CRT da lista de definições do pré-processador para permitir que o código de inicialização CRT seja incluído. Para obter mais informações, consulte Página geral de propriedades (Projeto).

    • Se possível, remova as chamadas para funções CRT que exigem código de inicialização CRT. Em vez disso, use seus equivalentes Win32. Por exemplo, use lstrcmp em vez de strcmp. Funções conhecidas que requerem código de inicialização CRT são algumas das funções de cadeia de caracteres e ponto flutuante.

Questões de coerência

Atualmente, não há um padrão para a decoração de nomes C++ entre fornecedores de compiladores ou mesmo entre diferentes versões do mesmo compilador. Arquivos de objeto compilados com compiladores diferentes podem não usar o mesmo esquema de nomenclatura. Linká-los pode causar erro LNK2001.

Misturar opções de compilação embutidas e não embutidas em módulos diferentes pode causar LNK2001. Se uma biblioteca C++ for criada com a função inlining ativada (/Ob1 ou /Ob2), mas o arquivo de cabeçalho correspondente que descreve as funções estiver inlining desativado (sem inline palavra-chave), esse erro ocorrerá. Para corrigir esse problema, defina as funções inline no arquivo de cabeçalho que você inclui em outros arquivos de origem.

Se você usar a #pragma inline_depth diretiva do compilador, certifique-se de ter definido um valor de 2 ou superior e certifique-se de usar também a opção de compilador /Ob1 ou /Ob2 .

Este erro pode ocorrer se omitir a opção LINK /NOENTRY quando cria uma DLL apenas de recursos. Para corrigir esse problema, adicione a opção /NOENTRY ao comando link.

Este erro pode ocorrer se você usar configurações incorretas /SUBSYSTEM ou /ENTRY em seu projeto. Por exemplo, se você escrever um aplicativo de console e especificar /SUBSYSTEM:WINDOWS, um erro externo não resolvido será gerado para WinMain. Para corrigir esse problema, certifique-se de que as opções correspondem ao tipo de projeto. Para obter mais informações sobre essas opções e pontos de entrada, consulte as opções de vinculador /SUBSYSTEM e /ENTRY .

Problemas com o símbolo do arquivo .def exportado

Este erro ocorre quando uma exportação listada em um arquivo .def não é encontrada. Pode ser porque a exportação não existe, está escrita incorretamente ou usa nomes decorados em C++. Um arquivo .def não usa nomes decorados. Para corrigir este problema, remova exportações desnecessárias e use declarações extern "C" para símbolos exportados.

Use o nome decorado para localizar o erro

O compilador C++ e o vinculador usam Name Decoration, também conhecido como name-mangling. A decoração de nomes codifica informações adicionais sobre o tipo de uma variável no nome do símbolo. O nome do símbolo de uma função codifica seu tipo de retorno, tipos de parâmetro, escopo e convenção de chamada. Este nome decorado é o nome do símbolo que o vinculador procura para resolver símbolos externos.

Um erro de link pode ocorrer se a declaração de uma função ou variável não corresponder exatamente à definição da função ou variável. Isso porque qualquer diferença passa a fazer parte do nome do símbolo a ser correspondido. O erro pode acontecer mesmo se o mesmo arquivo de cabeçalho for usado no código de chamada e no código definidor. Uma maneira de isso ocorrer é se você compilar os arquivos de origem usando diferentes sinalizadores do compilador. Por exemplo, se o código for compilado para usar a convenção de chamada __vectorcall, mas ligar a uma biblioteca que espera que os clientes chamem-na usando a convenção padrão de chamada __cdecl ou __fastcall. Neste caso, os símbolos não correspondem porque as convenções de chamada são diferentes.

Para ajudá-lo a encontrar a causa, a mensagem de erro mostra duas versões do nome. Ele exibe o "nome amigável", o nome usado no código-fonte, e o nome decorado (entre parênteses). Não é necessário saber interpretar o nome decorado. Você ainda pode procurar por ele e compará-lo com outros nomes decorados. As ferramentas de linha de comando podem ajudar a localizar e comparar o nome do símbolo esperado e o nome real do símbolo:

  • As opções /EXPORTS e /SYMBOLS da ferramenta de linha de comando DUMPBIN são úteis aqui. Eles podem ajudá-lo a descobrir quais símbolos são definidos em seus arquivos .dll e objetos ou bibliotecas. Você pode usar a lista de símbolos para verificar se os nomes decorados exportados correspondem aos nomes decorados que o vinculador procura.

  • Em alguns casos, o vinculador só pode relatar o nome decorado para um símbolo. Você pode usar a ferramenta de linha de comando UNDNAME para obter a forma não decorada de um nome decorado.

Recursos adicionais

Para obter mais informações, consulte a pergunta no Stack Overflow "O que é um erro de referência indefinida/símbolo externo não resolvido e como faço para corrigi-lo?".