Errore degli strumenti del linker LNK2001

simbolo esterno non risolto "simbolo"

Il codice compilato esegue un riferimento o una chiamata al simbolo. Il simbolo non è definito in nessuna libreria o file oggetto ricercati dal linker.

Questo messaggio di errore è seguito da un errore irreversibile LNK1120. Per correggere l'errore LNK1120, correggere prima tutti gli errori di LNK2001 e LNK2019.

Esistono molti modi per ottenere errori LNK2001. Tutti implicano un riferimento a una funzione o a una variabile per cui il linker non è in grado di risolvere o di trovare una definizione. Il compilatore può identificare quando il codice non dichiara un simbolo, ma non quando non ne definisce uno. Ciò è dovuto al fatto che la definizione può trovarsi in un file o una libreria di origine diversi. Se il codice fa riferimento a un simbolo, ma non viene mai definito, il linker genera un errore.

Che cos'è un simbolo esterno non risolto?

Un simbolo è il nome interno di una funzione o di una variabile globale. È il formato del nome usato o definito in un file o una libreria di oggetti compilati. Una variabile globale viene definita nel file di oggetto in cui viene allocata l'archiviazione. Una funzione viene definita nel file oggetto in cui viene inserito il codice compilato per il corpo della funzione. Un simbolo esterno è un riferimento in un file oggetto, ma definito in un file di libreria o oggetto diverso. Un simbolo esportato è uno reso pubblicamente disponibile dal file oggetto o dalla libreria che lo definisce.

Per creare un'applicazione o una DLL, ogni simbolo usato deve avere una definizione. Il linker deve risolvere o trovare la definizione corrispondente per ogni simbolo esterno a cui fa riferimento ogni file oggetto. Il linker genera un errore quando non riesce a risolvere un simbolo esterno. Significa che il linker non è riuscito a trovare una definizione di simbolo esportata corrispondente in uno dei file collegati.

Questo errore può verificarsi:

  • Quando il progetto manca un riferimento a una libreria (. LIB) o oggetto (. File OBJ). Per risolvere questo problema, aggiungere un riferimento alla libreria o al file di oggetto richiesto al progetto. Per altre informazioni, vedere lib Files as linker input .For more information, see lib Files as linker input.

  • Quando il progetto ha un riferimento a una libreria (. LIB) o oggetto (. File OBJ) che a sua volta richiede simboli da un'altra libreria. Può verificarsi anche se non si chiamano funzioni che causano la dipendenza. Per risolvere questo problema, aggiungere un riferimento all'altra libreria al progetto. Per altre informazioni, vedere Understanding the classic model for linking: Taking symbols along for the ride.For more information, see Understanding the classic model for linking: Taking symbols along for the ride.

  • Se si usano le opzioni /NODEFAULTLIB o /Zl . Quando si specificano queste opzioni, le librerie che contengono il codice richiesto non vengono collegate al progetto, a meno che non siano state incluse in modo esplicito. Per risolvere questo problema, includere in modo esplicito tutte le librerie usate nella riga di comando del collegamento. Se quando si usano queste opzioni vengono visualizzati molti nomi di funzioni CRT o libreria standard mancanti, includere in modo esplicito le DLL della libreria CRT e standard o i file di libreria nel collegamento.

  • Se si esegue la compilazione usando l'opzione /clr . Potrebbe essere presente un riferimento mancante a .cctor. Per altre informazioni su come risolvere questo problema, vedere Inizializzazione di assembly misti.

  • Se si collegano alle librerie in modalità di rilascio durante la compilazione di una versione di debug di un'applicazione. Analogamente, se si usano opzioni /MTd o /MDd o si definiscono _DEBUG e quindi si collegano alle librerie di versione, è consigliabile prevedere molti potenziali esterni non risolti, tra gli altri problemi. Il collegamento di una compilazione in modalità di rilascio con le librerie di debug causa anche problemi simili. Per risolvere questo problema, assicurarsi di usare le librerie di debug nelle compilazioni di debug e le librerie di vendita al dettaglio nelle build di vendita al dettaglio.

  • Se il codice fa riferimento a un simbolo di una versione della libreria, ma si collega una versione diversa della libreria. In genere, non è possibile combinare file oggetto o librerie compilati per versioni diverse del compilatore. Le librerie incluse in una versione possono contenere simboli che non sono disponibili nelle librerie incluse in altre versioni. Per risolvere questo problema, compilare tutti i file oggetto e le librerie con la stessa versione del compilatore prima di collegarli. Per altre informazioni, vedere Compatibilità binaria C++ tra le versioni di Visual Studio.

  • Se i percorsi della libreria non sono aggiornati. La finestra di dialogo Strumenti > Opzioni > progetti > VC++ directory, sotto la selezione Dei file di libreria, consente di modificare l'ordine di ricerca della libreria. La cartella Linker nella finestra di dialogo Pagine delle proprietà del progetto può contenere anche percorsi non aggiornati.

  • Quando viene installato un nuovo Windows SDK (ad esempio in un percorso diverso). L'ordine di ricerca della libreria deve essere aggiornato in modo che punti alla nuova posizione. In genere, è necessario inserire il percorso della nuova directory SDK include e lib davanti al percorso predefinito di Visual C++. Inoltre, un progetto contenente percorsi incorporati può ancora puntare a percorsi obsoleti validi, ma non aggiornati. Aggiornare i percorsi per le nuove funzionalità aggiunte dalla nuova versione installata in un percorso diverso.

  • Se si compila nella riga di comando e sono state create variabili di ambiente personalizzate. Verificare che i percorsi degli strumenti, delle librerie e dei file di intestazione vadano a una versione coerente. Per altre informazioni, vedere Usare il set di strumenti MSVC dalla riga di comando.

Problemi di codifica

Questo errore può dipendere dalle cause seguenti:

  • Caso non corrispondente nel codice sorgente o nel file module-definition (con estensione def). Ad esempio, se si assegna un nome a una variabile var1 in un file di origine C++ e si tenta di accedervi come VAR1 in un altro, viene generato questo errore. Per risolvere questo problema, usare nomi digitati in modo coerente e con maiuscole e minuscole.

  • Progetto che usa l'inlining della funzione. Può verificarsi quando si definiscono le funzioni come inline in un file di origine, anziché in un file di intestazione. Le funzioni inlined non possono essere visualizzate all'esterno del file di origine che le definisce. Per risolvere questo problema, definire le funzioni inlined nelle intestazioni in cui sono dichiarate.

  • Chiamata di una funzione C da un programma C++ senza usare una extern "C" dichiarazione per la funzione C. Il compilatore usa diverse convenzioni di denominazione dei simboli interni per il codice C e C++. Il nome del simbolo interno è ciò che il linker cerca durante la risoluzione dei simboli. Per risolvere questo problema, usare un extern "C" wrapper per tutte le dichiarazioni di funzioni C usate nel codice C++, che fa sì che il compilatore usi la convenzione di denominazione interna C per tali simboli. Le opzioni del compilatore /Tp e /Tc causano rispettivamente la compilazione dei file come C++ o C, indipendentemente dall'estensione del nome file. Queste opzioni possono causare nomi di funzione interni diversi da quello previsto.

  • Tentativo di fare riferimento a funzioni o dati che non dispongono di collegamenti esterni. In C++, le funzioni inline e const i dati hanno un collegamento interno a meno che non venga specificato in modo esplicito come extern. Per risolvere questo problema, usare dichiarazioni esplicite extern sui simboli a cui si fa riferimento all'esterno del file di origine di definizione.

  • Corpo della funzione o definizione di variabile mancante . Questo errore è comune quando si dichiara, ma non si definiscono, variabili, funzioni o classi nel codice. Il compilatore richiede solo un prototipo di funzione o extern una dichiarazione di variabile per generare un file di oggetto senza errori, ma il linker non può risolvere una chiamata alla funzione o un riferimento alla variabile perché non è disponibile codice funzione o spazio variabile riservato. Per risolvere questo problema, assicurarsi di definire tutte le funzioni e le variabili a cui si fa riferimento in un file di origine o in una libreria collegati.

  • Chiamata di funzione che usa tipi restituiti e di parametri o convenzioni di chiamata che non corrispondono a quelle nella definizione della funzione. Nei file di oggetto C++ la decorazione nome codifica la convenzione di chiamata, l'ambito della classe o dello spazio dei nomi e i tipi restituiti e di parametri di una funzione. La stringa codificata diventa parte del nome finale della funzione decorata. Questo nome viene usato dal linker per risolvere o trovare una corrispondenza con le chiamate alla funzione da altri file oggetto. Per risolvere questo problema, assicurarsi che la dichiarazione, la definizione e le chiamate di funzione usino tutti gli stessi ambiti, tipi e convenzioni di chiamata.

  • Codice C++ chiamato, quando si include un prototipo di funzione in una definizione di classe, ma non includere l'implementazione della funzione. Per risolvere questo problema, assicurarsi di fornire una definizione per tutti i membri della classe chiamati.

  • Tentativo di chiamare una funzione virtuale pura da una classe di base astratta. Una funzione virtuale pura non ha un'implementazione della classe di base. Per risolvere questo problema, assicurarsi che tutte le funzioni virtuali chiamate siano implementate.

  • Tentativo di usare una variabile dichiarata all'interno di una funzione (una variabile locale) all'esterno dell'ambito di tale funzione. Per risolvere questo problema, rimuovere il riferimento alla variabile che non si trova nell'ambito o spostare la variabile in un ambito superiore.

  • Quando si compila una versione release di un progetto ATL, generando un messaggio che indica che è necessario il codice di avvio CRT. Per risolvere il problema, eseguire una delle operazioni seguenti:

    • Rimuovere _ATL_MIN_CRT dall'elenco di definizioni del preprocessore per consentire l'inserimento del codice di avvio CRT. Per altre informazioni, vedere Pagina delle proprietà Generale (Progetto).

    • Se possibile, rimuovere le chiamate alle funzioni CRT che richiedono codice di avvio CRT. Usare invece gli equivalenti Win32. Usare, ad esempio, lstrcmp invece di strcmp. Le funzioni note che richiedono il codice di avvio CRT sono alcune delle funzioni stringa e a virgola mobile.

Problemi di coerenza

Attualmente non esiste uno standard per la decorazione dei nomi C++ tra i fornitori del compilatore o anche tra versioni diverse dello stesso compilatore. I file oggetto compilati con compilatori diversi potrebbero non usare lo stesso schema di denominazione. Il collegamento può causare errori LNK2001.

La combinazione di opzioni di compilazione inline e non inline in moduli diversi può causare LNK2001. Se viene creata una libreria C++ con l'inlining della funzione attivata (/Ob1 o /Ob2), ma il file di intestazione corrispondente che descrive le funzioni è disattivato (nessuna inline parola chiave), questo errore si verifica. Per risolvere questo problema, definire le funzioni inline nel file di intestazione che si include in altri file di origine.

Se si usa la #pragma inline_depth direttiva del compilatore, assicurarsi di aver impostato un valore pari o superiore a 2 e assicurarsi di usare anche l'opzione del compilatore /Ob1 o /Ob2 .

Questo errore può verificarsi se si omette l'opzione LINK /NOENTRY quando si crea una DLL solo risorsa. Per risolvere questo problema, aggiungere l'opzione /NOENTRY al comando di collegamento.

Questo errore può verificarsi se si usano impostazioni /SUBSYSTEM o /ENTRY non corrette nel progetto. Ad esempio, se si scrive un'applicazione console e si specifica /SUBSYSTEM:WINDOWS, viene generato un errore esterno non risolto per WinMain. Per risolvere questo problema, assicurarsi di associare le opzioni al tipo di progetto. Per altre informazioni su queste opzioni e punti di ingresso, vedere le opzioni /SUBSYSTEM e /ENTRY linker.

Problemi di simboli del file con estensione def esportati

Questo errore si verifica quando un'esportazione elencata in un file con estensione def non viene trovata. Potrebbe essere dovuto al fatto che l'esportazione non esiste, viene digitata in modo non corretto o usa nomi decorati C++. Un file con estensione def non accetta nomi decorati. Per risolvere questo problema, rimuovere le esportazioni non richieste e usare extern "C" le dichiarazioni per i simboli esportati.

Usare il nome decorato per trovare l'errore

Il compilatore C++ e il linker usano Name Decoration, noto anche come mangling name-mangling. La decorazione del nome codifica informazioni aggiuntive sul tipo di una variabile nel nome del simbolo. Il nome del simbolo per una funzione codifica il tipo restituito, i tipi di parametro, l'ambito e la convenzione di chiamata. Questo nome decorato è il nome del simbolo che il linker cerca per risolvere i simboli esterni.

Un errore di collegamento può determinare se la dichiarazione di una funzione o di una variabile non corrisponde esattamente alla definizione della funzione o della variabile. Ciò è dovuto al fatto che qualsiasi differenza diventa parte del nome del simbolo da trovare. L'errore può verificarsi anche se lo stesso file di intestazione viene usato sia nel codice chiamante che nel codice di definizione. Un modo in cui può verificarsi è se si compilano i file di origine usando flag del compilatore diversi. Ad esempio, se il codice viene compilato per usare la __vectorcall convenzione di chiamata, ma si collega a una libreria che prevede che i client lo chiamino usando la convenzione predefinita __cdecl o __fastcall chiamante. In questo caso, i simboli non corrispondono perché le convenzioni di chiamata sono diverse.

Per individuare la causa, il messaggio di errore mostra due versioni del nome. Visualizza sia il "nome descrittivo", il nome usato nel codice sorgente che il nome decorato (tra parentesi). Non è necessario sapere come interpretare il nome decorato. È comunque possibile cercare e confrontarlo con altri nomi decorati. Gli strumenti da riga di comando consentono di trovare e confrontare il nome del simbolo previsto e il nome effettivo del simbolo:

  • Le opzioni /EXPORT e /SYMBOLS dello strumento da riga di comando DUMPBIN sono utili qui. Possono essere utili per individuare i simboli definiti nei file con estensione dll e di libreria o oggetti. È possibile utilizzare l'elenco dei simboli per verificare che i nomi decorati esportati corrispondano ai nomi decorati cercati dal linker.

  • In alcuni casi, il linker può segnalare solo il nome decorato per un simbolo. È possibile usare lo strumento da riga di comando UNDNAME per ottenere la forma non dichiarata di un nome decorato.

Risorse aggiuntive

Per altre informazioni, vedere la domanda Stack Overflow "What is an undefined reference/unresolved external symbol error and how do I fix it?".For more information, see the Stack Overflow question "What is an undefined reference/unresolved external symbol error and how do I fix it?".