Risoluzione di LNK4098: defaultlib 'MSVCRT' è in conflitto


217

Questo avviso:

LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts
  with use of other libs; use /NODEFAULTLIB:library

è un avviso abbastanza comune in Visual Studio. Mi piacerebbe capire il motivo esatto e il modo giusto (se non del tutto) di gestirlo.

Questo si presenta in una build di debug, compilata con /MDd. Il progetto è collegato a cose come Windows Version.dlle con le pdh.dllstesse connessioni MSVCRT.dll. Ovviamente, non ho le versioni di debug di questi e non riesco a compilarli.

Quindi ho aggiunto /NODEFAULTLIB:MSVCRTalla riga di comando del linker e in realtà ha rimosso l'avviso. Ma cosa fa veramente? E perché è necessario?

Risposte:


273

Esistono 4 versioni delle librerie di collegamento CRT presenti in vc \ lib:

  • libcmt.lib: libreria di link CRT statica per una build di rilascio (/ MT)
  • libcmtd.lib: libreria di link CRT statica per una build di debug (/ MTd)
  • msvcrt.lib: libreria di importazione per la versione DLL di rilascio del CRT (/ MD)
  • msvcrtd.lib: libreria di importazione per la versione DLL di debug di CRT (/ MDd)

Guarda le opzioni del linker, Progetto + Proprietà, Linker, Riga di comando. Nota come queste librerie non sono menzionate qui. Il linker individua automaticamente quale opzione / M è stata utilizzata dal compilatore e quale .lib deve essere collegato tramite una direttiva di commento #pragma. Molto importante, otterrai errori di collegamento orribili e errori di runtime difficili da diagnosticare se ci fosse una discrepanza tra l'opzione / M e il .lib con cui ti colleghi.

Vedrai il messaggio di errore che hai citato quando al linker viene detto sia di collegarsi a msvcrt.lib che a libcmt.lib. Ciò accadrà se si collega il codice compilato con / MT con il codice collegato con / MD. Può esistere una sola versione del CRT.

/ NODEFAULTLIB dice al linker di ignorare la direttiva di commento #pragma generata dal codice compilato / MT. Ciò potrebbe funzionare, sebbene una serie di altri errori del linker non sia rara. Cose come errno , che è un int esterno nella versione CRT statica ma con macro-ed a una funzione nella versione DLL. A molti altri piace questo.

Bene, risolvi questo problema nel modo giusto, trova il file .obj o .lib che stai collegando che è stato compilato con l'opzione / M errata. Se non si ha idea, è possibile trovarlo greppando i file .obj / .lib per "/ MT"

A proposito: gli eseguibili di Windows (come version.dll) hanno la loro versione CRT per svolgere il loro lavoro. Si trova in c: \ windows \ system32, non puoi usarlo in modo affidabile per i tuoi programmi, le sue intestazioni CRT non sono disponibili da nessuna parte. La DLL CRT utilizzata dal programma ha un nome diverso (come msvcrt90.dll).


2
Grazie a questo post, ho continuato a cercare un .lib che stava ancora usando / MDd e alla fine ne ho trovato uno! Grazie, +1
ceztko,

64
Un trucco che ho appena imparato a rintracciare le librerie che stanno estraendo le librerie CRT sbagliate è quello di aggiungere /verbose:liballe opzioni di linker aggiuntive. Mostra l'ordine in cui sono caricati i file .lib, che consente di vedere dove è stato
inserito

1
Hans, quanto è pericoloso? Se non riusciamo a risolverlo (riceviamo una lib compilata dal nostro fornitore), quali conseguenze potremmo affrontare?
Ivan Nikitin,

3
Ho trovato utile il commento di @obmarg ma non ero ancora sicuro di come utilizzare l'output dettagliato fino a quando non ho trovato msdn.microsoft.com/en-us/library/aa267384(v=vs.60).aspx che dice che l'output dettagliato sarà indica solo tutte le librerie di runtime coinvolte nel problema del collegamento. Devi ancora capire quale input di link è stato compilato con la libreria di runtime in conflitto.
buzz3791,

4
@ buzz3791 use / verbose anziché / verbose: lib. Le informazioni visualizzate includono il processo di ricerca della libreria ed elenca ogni libreria e nome dell'oggetto (con percorso completo), il simbolo viene risolto dalla libreria e un elenco di oggetti che fanno riferimento al simbolo. / verbose può visualizzare tutte le informazioni necessarie per trovare il cattivo che causa i conflitti.
Yang Kui,

46

Significa che una delle DLL dipendenti viene compilata con una libreria di runtime diversa .

Progetto -> Proprietà -> C / C ++ -> Generazione di codice -> Libreria di runtime

Andare su tutte le librerie e vedere che sono compilate allo stesso modo.

Maggiori informazioni su questo errore in questo link:

avviso LNK4098: defaultlib "LIBCD" è in conflitto con l'uso di altre librerie


Questa era la ragione dell'errore! Grazie per il consiglio.
rkachach,

1
Questa è la risposta migliore per i programmatori meno esperti.
Meolic,

32

IMO questo link di Yochai Timmer era molto buono e pertinente ma doloroso da leggere. Ho scritto un riassunto.

Yochai, se mai hai letto questo, per favore vedi la nota alla fine.


Per il post originale leggi: avviso LNK4098: defaultlib "LIBCD" è in conflitto con l'uso di altre librerie

Errore

LINK: avviso LNK4098: defaultlib "LIBCD" è in conflitto con l'uso di altre librerie; use / NODEFAULTLIB: libreria

Senso

una parte del sistema è stata compilata per utilizzare una libreria a thread singolo standard (libc) con informazioni di debug (libcd) collegata staticamente

mentre un'altra parte del sistema è stata compilata per utilizzare una libreria standard multi-thread senza informazioni di debug che risiede in una DLL e utilizza il collegamento dinamico

Come risolvere

  • Ignora l'avviso, dopo tutto è solo un avvertimento. Tuttavia, il programma ora contiene più istanze delle stesse funzioni.

  • Utilizzare l'opzione linker / NODEFAULTLIB: lib. Questa non è una soluzione completa, anche se riesci a collegare il tuo programma in questo modo stai ignorando un segnale di avvertimento: il codice è stato compilato per ambienti diversi, parte del tuo codice potrebbe essere compilato per un singolo modello thread mentre l'altro codice è multi-thread.

  • [...] navigare in tutte le librerie e assicurarsi che abbiano le impostazioni di collegamento corrette

In quest'ultimo caso, come indicato nel post originale, possono sorgere due problemi comuni:

  • Hai una libreria di terze parti collegata in modo diverso alla tua applicazione.

  • Hai altre direttive integrate nel tuo codice: normalmente si tratta dell'MFC. Se qualsiasi modulo nel tuo sistema si collega a MFC, tutti i tuoi moduli devono nominalmente collegarsi alla stessa versione di MFC.

In questi casi, assicurati di aver compreso il problema e di decidere tra le soluzioni.


Nota: volevo includere quel riassunto del link di Yochai Timmer nella sua risposta, ma poiché alcune persone hanno difficoltà a rivedere correttamente le modifiche, ho dovuto scriverlo in una risposta separata. scusate


7

Lo capisco ogni volta che voglio creare un'applicazione in VC ++.

Fare clic con il tasto destro del mouse sul progetto, selezionare Proprietà quindi in 'Proprietà di configurazione | C / C ++ | Generazione di codice ", selezionare" Debug multi-thread (/ MTd) "per la configurazione di debug.

Nota che questo non cambia l'impostazione per la configurazione della tua versione: dovrai andare nella stessa posizione e selezionare "Multi-thread (/ MT)" per la versione.


4

Fare clic con il tasto destro del mouse sul progetto, selezionare Proprietà quindi in 'Proprietà di configurazione | Linker | Input | Ignora la libreria specifica e scrivi msvcrtd.lib

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.