Rilevata mancata corrispondenza per "RuntimeLibrary"


113

Ho scaricato ed estratto Crypto ++ in C: \ cryptopp. Ho usato Visual Studio Express 2012 per creare tutti i progetti all'interno (come indicato nel file readme) e tutto è stato creato con successo. Quindi ho creato un progetto di prova in un'altra cartella e ho aggiunto cryptolib come dipendenza. Successivamente, ho aggiunto il percorso di inclusione in modo da poter includere facilmente tutte le intestazioni. Quando ho provato a compilare, ho ricevuto un errore sui simboli non risolti.

Per rimediare a ciò, ho aggiunto C:\cryptopp\Win32\Output\Debug\cryptlib.libper collegare ulteriori dipendenze. Ora ottengo questo errore:

Error   1   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(cryptlib.obj)    CryptoTest
Error   2   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(iterhash.obj)    CryptoTest
Error   3   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(sha.obj) CryptoTest
Error   4   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(pch.obj) CryptoTest
Error   5   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(misc.obj)    CryptoTest
Error   6   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(queue.obj)   CryptoTest
Error   7   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(algparam.obj)    CryptoTest
Error   8   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(filters.obj) CryptoTest
Error   9   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(fips140.obj) CryptoTest
Error   10  error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(cpu.obj) CryptoTest
Error   11  error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(mqueue.obj)  CryptoTest

Ricevo anche:

Error   12  error LNK2005: "public: __thiscall std::_Container_base12::_Container_base12(void)" (??0_Container_base12@std@@QAE@XZ) already defined in cryptlib.lib(cryptlib.obj)    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\msvcprtd.lib(MSVCP110D.dll)   CryptoTest
Error   13  error LNK2005: "public: __thiscall std::_Container_base12::~_Container_base12(void)" (??1_Container_base12@std@@QAE@XZ) already defined in cryptlib.lib(cryptlib.obj)   C:\Data\Work\C++ VS\CryptoTest\CryptoTest\msvcprtd.lib(MSVCP110D.dll)   CryptoTest
Error   14  error LNK2005: "public: void __thiscall std::_Container_base12::_Orphan_all(void)" (?_Orphan_all@_Container_base12@std@@QAEXXZ) already defined in cryptlib.lib(cryptlib.obj)   C:\Data\Work\C++ VS\CryptoTest\CryptoTest\msvcprtd.lib(MSVCP110D.dll)   CryptoTest
Error   15  error LNK2005: "public: __thiscall std::locale::id::id(unsigned int)" (??0id@locale@std@@QAE@I@Z) already defined in cryptlib.lib(iterhash.obj) C:\Data\Work\C++ VS\CryptoTest\CryptoTest\msvcprtd.lib(MSVCP110D.dll)   CryptoTest
Warning 16  warning LNK4098: defaultlib 'LIBCMTD' conflicts with use of other libs; use /NODEFAULTLIB:library   C:\Data\Work\C++ VS\CryptoTest\CryptoTest\LINK  CryptoTest
Error   17  error LNK1169: one or more multiply defined symbols found   C:\Data\Work\C++ VS\CryptoTest\Debug\CryptoTest.exe 1   1   CryptoTest

Il codice che ho provato a compilare era semplice (l'ho preso da un altro sito):

#include <iostream>
#include <string>
#include "sha.h"
#include "hex.h"
using namespace std;

string SHA256(string data) {
    byte const* pbData = (byte*) data.data();
    unsigned int nDataLen = data.size();
    byte abDigest[32];

    CryptoPP::SHA256().CalculateDigest(abDigest, pbData, nDataLen);

    return string((char*)abDigest);
}

int main(void) {

    return 0;
}

Qualche idea su come risolvere questo problema? In questo momento mi serve solo SHA-256, nient'altro. Sto usando Windows 7 a 64 bit e oggi ho scaricato VS C ++, quindi dovrebbe essere la versione più recente.



1
Ho impostato la libreria runtime del mio progetto su debug multi-thread (quella era l'impostazione utilizzata in crypto ++) e ora si compila! :) Grazie mille.
Momonga

I problemi si sono verificati molto prima durante la corsa VCUpgrade. Stai vedendo i sintomi dell'errore VCUpgrade che ti è stato segnalato come successo .
jww

Risposte:


233

(Questo è già risposto nei commenti, ma poiché manca una risposta effettiva , sto scrivendo questo.)

Questo problema si verifica nelle versioni più recenti di Visual C ++ (le versioni precedenti di solito collegavano il programma in modo silenzioso e si bloccava e si bruciava in fase di esecuzione.) Significa che alcune delle librerie che stai collegando al tuo programma (o anche alcuni dei sorgenti file all'interno del programma stesso) utilizzano versioni diverse di CRT (la libreria C RunTime).

Per correggere questo errore, è necessario entrare nella propria Project Properties(e / o in quelle delle librerie che si stanno utilizzando) quindi in C/C++, quindi Code Generatione controllare il valore di Runtime Library; dovrebbe essere esattamente lo stesso per tutti i file e le librerie che colleghi insieme. (Le regole sono un po 'più rilassate per il collegamento con le DLL, ma non entrerò nel "perché" e in maggiori dettagli qui.)

Attualmente sono disponibili quattro opzioni per questa impostazione:

  1. Debug multithread
  2. DLL di debug multithread
  3. Versione multithread
  4. DLL di rilascio multithread

Il tuo problema particolare sembra derivare dal collegamento di una libreria costruita con "Multithreaded Debug" (cioè CRT di debug multithread statico) con un programma che viene creato utilizzando l' impostazione " DLL di debug multithread " (cioè CRT di debug multithread dinamico). questa impostazione nella libreria o nel programma. Per ora, suggerisco di cambiarlo nel tuo programma.

Si noti che poiché i progetti di Visual Studio utilizzano diversi set di impostazioni del progetto per le build di debug e di rilascio (e build a 32/64 bit), è necessario assicurarsi che le impostazioni corrispondano in tutte queste configurazioni di progetto.

Per (alcune) ulteriori informazioni, puoi vedere questi (collegati da un commento sopra):

  1. Avviso degli strumenti del linker LNK4098 su MSDN
  2. / MD, / ML, / MT, / LD (Use Run-Time Library) su MSDN
  3. Errori di compilazione con VC11 Beta: il mix di librerie MTd con exe MDd non riesce a collegarsi a Bugzilla @ Mozilla

AGGIORNAMENTO : (Questo è in risposta a un commento che chiede il motivo per cui è necessario prestare molta attenzione.)

Se due parti di codice che stiamo collegando insieme si collegano e utilizzano la libreria standard, la libreria standard deve essere la stessa per entrambe, a meno che non si presti molta attenzione a come le nostre due parti di codice interagiscono e passano i dati. In generale, direi che per quasi tutte le situazioni usa la stessa identica versione del runtime della libreria standard (per quanto riguarda il debug / rilascio, i thread e ovviamente la versione di Visual C ++, tra le altre cose come il debug dell'iteratore, ecc.)

La parte più importante del problema è questa: avere la stessa idea sulla dimensione degli oggetti su entrambi i lati di una chiamata di funzione .

Si consideri ad esempio che le due parti di codice precedenti sono chiamate Ae B. A viene compilato con una versione della libreria standard e B con un'altra. Nella vista di A, un oggetto casuale che una funzione standard gli restituisce (ad esempio un blocco di memoria o un iteratore o un FILEoggetto o qualsiasi altra cosa) ha una dimensione e un layout specifici (ricorda che il layout della struttura è determinato e fissato al momento della compilazione in C / C ++.) Per diversi motivi, l'idea di B della dimensione / layout degli stessi oggetti è diversa (può essere a causa di ulteriori informazioni di debug, evoluzione naturale delle strutture dati nel tempo, ecc.)

Ora, se A chiama la libreria standard e recupera un oggetto, quindi passa quell'oggetto a B e B tocca quell'oggetto in qualsiasi modo, è probabile che B rovini quell'oggetto (es. Scrive il campo sbagliato, o oltre la fine di esso, ecc.)

Quanto sopra non è l'unico tipo di problemi che possono verificarsi. Anche gli oggetti globali o statici interni nella libreria standard possono causare problemi. E ci sono anche classi di problemi più oscure.

Tutto ciò diventa più strano in alcuni aspetti quando si utilizzano DLL (libreria runtime dinamica) invece di libs (libreria runtime statica).

Questa situazione può applicarsi a qualsiasi libreria utilizzata da due parti di codice che lavorano insieme, ma la libreria standard viene utilizzata dalla maggior parte (se non quasi tutti) i programmi e ciò aumenta le possibilità di conflitto.

Quello che ho descritto è ovviamente una versione annacquata e semplificata del vero casino che ti aspetta se mescoli le versioni della libreria. Spero che ti dia un'idea del motivo per cui non dovresti farlo!


Sono un po 'confuso. L' errore di OP è LNK2038 . Dato che non accade con tutte le librerie, ho il sospetto Crypto ++ giocherella con alcune impostazioni CRT che rendono impossibile mescolare sapori CRT - di solito si tratta solo di un avvertimento (LNK4098) e si può essere al sicuro se si sa cosa fare (non raccomandato, ma possibile con limitazioni, vedere ad esempio stackoverflow.com/a/19944935/948581 ). Non so perché Crypto ++ sia influenzato in questo modo, però.

1
@Tibo: queste non sono librerie di importazione per DLL; Credo che Crypto ++ sia effettivamente collegato staticamente al programma qui. Ciò significa che qualsiasi mancata corrispondenza nella libreria standard collegata a un modulo rispetto a un altro (probabilmente) viola la "regola di una definizione". Che è un male. Questo non era un errore, poiché il linker non era nemmeno in grado di rilevarlo (i nomi di funzione / tipo erano gli stessi, ma i loro corpi e definizioni differivano in modo significativo) fino a VC10 quando il linker / bibliotecario iniziò a "taggare" i moduli ha prodotto con informazioni extra sulla configurazione della build ...
yzt

@Tibo: ... (continua dal commento precedente) Ad esempio, guarda il primo blocco di errori che l'OP sta segnalando. Lì, " RuntimeLibrary " è un tag sia sulla libreria Crypto ++ che sul file oggetto per il programma dell'OP, e il suo valore è " MDd_DynamicDebug " per uno di essi e " MTd_StaticDebug " per l'altro. In questo modo, il linker che sta tentando di collegare due file oggetto insieme può rilevare e segnalare un'intera nuova classe di errori, dato che i linker che hanno prodotto quei file oggetto li hanno etichettati con tutte le informazioni rilevanti, in particolare qualsiasi impostazione che potrebbe potenzialmente violare ODR.
yzt

Anche se sono abbastanza d'accordo con te, c'è ancora un'area di mistero qui. Per quanto riguarda il problema dell'OP, immagino che includa "dll.h" da Crypto ++, e quindi cerchi di collegarsi alla lib statica invece della libreria di importazione della DLL. Ma ho visto gli stessi errori su un computer, non su un altro (VS2013 ultimate sp4 -> errore, VS2013 community sp5 -> ok) ...

1
@yzt ho trovato una soluzione. Invece di utilizzare / ZW swicth, Windows fornisce un modo per utilizzare l'API WinRT tramite COM utilizzando un wrapper chiamato WRL. È solo che non usare / ZW rende la codifica un po 'difficile poiché nasconde i dettagli di implementazione COM, ma è possibile usare WinRT senza / ZW.
Sahil Singh

3

Ho scaricato ed estratto Crypto ++ in C: \ cryptopp. Ho usato Visual Studio Express 2012 per creare tutti i progetti all'interno (come indicato nel file readme) e tutto è stato creato con successo. Quindi ho creato un progetto di prova in un'altra cartella e ho aggiunto cryptolib come dipendenza.

La conversione probabilmente non ha avuto successo. L'unica cosa che ha avuto successo è stata l'esecuzione di VCUpgrade. La conversione effettiva in sé non è riuscita ma non lo sai finché non riscontri gli errori che stai vedendo. Per alcuni dettagli, vedere Visual Studio nel wiki Crypto ++.


Qualche idea su come risolvere questo problema?

Per risolvere i problemi, è necessario eseguire il download vs2010.zipse si desidera un collegamento runtime C / C ++ statico ( /MTo /MTd) o vs2010-dynamic.zipse si desidera un collegamento runtime C / C ++ dinamico ( /MTo /MTd). Entrambi risolvono gli errori latenti e silenziosi prodotti da VCUpgrade.


vs2010.zip, vs2010-dynamic.zipE vs2005-dynamic.zipsono costruiti con i più recenti fonti GitHub . Al momento della stesura di questo articolo (1 GIUGNO 2016), è effettivamente pre-Crypto ++ 5.6.4. Se stai usando i file ZIP con un Crypto ++ di livello inferiore, come 5.6.2 o 5.6.3, allora incorrerai in problemi minori.

Sono a conoscenza di due problemi minori. Il primo è una ridenominazione di bench.cppinbench1.cpp . Il suo errore è:

  • C1083: Cannot open source file: 'bench1.cpp': No such file or directory
  • LNK2001: unresolved external symbol "void __cdecl OutputResultOperations(char const *,char const *,bool,unsigned long,double)" (?OutputResultOperations@@YAXPBD0_NKN@Z)

La soluzione è (1) aprirlo cryptest.vcxprojnel blocco note, trovare bench1.cppe quindi rinominarlo in bench.cpp. Oppure (2) rinominare bench.cppin bench1.cppsul filesystem. Per favore non cancellare questo file.

Il secondo problema è un po 'più complicato perché è un bersaglio in movimento. Nelle versioni di livello inferiore, come 5.6.2 o 5.6.3, mancano le ultime classi disponibili in GitHub . I file di classe mancanti includono HKDF (5.6.3), RDRAND (5.6.3), RDSEED (5.6.3), ChaCha (5.6.4), BLAKE2 (5.6.4), Poly1305 (5.6.4), ecc.

La soluzione consiste nel rimuovere i file di origine mancanti dai file di progetto di Visual Studio poiché non esistono per le versioni di livello inferiore.

Un'altra opzione è aggiungere i file di classe mancanti dalle fonti più recenti, ma potrebbero esserci delle complicazioni. Ad esempio, molte delle fonti dipendono sottilmente dalle ultime config.h, cpu.he cpu.cpp. La "sottigliezza" è che non ti renderai conto che stai ricevendo una classe con prestazioni insufficienti.

Un esempio di classe con prestazioni insufficienti è BLAKE2. config.haggiunge il rilevamento ARM-32 e ARM-64 in fase di compilazione. cpu.he cpu.cppaggiunge il rilevamento delle istruzioni ARM in fase di esecuzione, che dipende dal rilevamento del tempo di compilazione. Se aggiungi BLAKE2 senza gli altri file, non si verifica alcun rilevamento e ottieni un'implementazione C / C ++ diretta. Probabilmente non ti renderai conto che stai perdendo l'opportunità NEON, che va da 9 a 12 cicli per byte contro 40 cicli per byte circa per vanilla C / C ++.


Ho seguito le istruzioni nel wiki di cryptopp, ho scaricato vs2010-dynamic.zip e ho incollato il suo contenuto sul codice cryptopp563. Costruito e ha alcuni file sorgente mancanti. Nessun problema, il wiki dice che lo zip è per l'ultimo progetto su GitHub e cancella semplicemente i file mancanti. Eliminata. Ora il progetto semplicemente non crea: 4 errori di collegamento, un esempio: errore LNK2001: simbolo esterno non risolto "void __cdecl OutputResultOperations (char const *, char const *, bool, unsigned long, double)" (? OutputResultOperations @@ YAXPBD0_NKN @ Z)
Yaniv

Si è scoperto che c'era un bench.cpp che mancava dal progetto. Ma anche dopo non si è compilato fino a quando non ho applicato questa correzione a fiptest.cpp github.com/weidai11/cryptopp/pull/151/files?diff=split Vorrei che facessero un po 'di ordine in questo, come aggiungere i file zip del progetto in git o qualcosa del genere. E sì, ho trascurato di dire che il mio compilatore è VS2015 update 2. In conclusione, segui i suggerimenti che ho scritto e funziona.
Yaniv

@Yaniv - Per il primo commento, cosa consigli in modo che gli altri utenti non abbiano problemi? Per il secondo commento, abbiamo in programma di prendere la patch una volta che l'avremo completamente testata. C'è qualcosa che possiamo fare nel frattempo? (Ho aggiunto ulteriori informazioni a questa risposta, ma voglio assicurarmi che gli utenti non abbiano problemi).
jww

In primo luogo, grazie mille per averlo fatto. Crypto ++ è davvero eccezionale. Per quanto riguarda i problemi di compilazione, cerca di mantenere i file sln di Windows e di progetto compatibili con i file più recenti del progetto, e poiché questi cambiano ovviamente, queste build di Windows dovrebbero essere in qualche modo collegate alla base di codice, e forse anche essere nell'albero dei sorgenti. Se è troppo, assicurati almeno che il file zip con l'ambiente di build di Visual Studio sia compatibile con l'attuale versione ufficiale stabile.
Yaniv

Per quanto riguarda la patch per fiptest.cpp, sembra essere qualcosa di diverso in VS2015, quindi immagino che chiunque desideri utilizzare VS2015 debba applicare questa patch. È solo un altro caso in un blocco #ifdef che sembra definire il giusto callback di debug per VS2015, ed è davvero facile da applicare manualmente.
Yaniv

3

Ho avuto questo problema insieme alla mancata corrispondenza in ITERATOR_DEBUG_LEVEL. Dato che il problema della domenica sera, dopotutto, sembrava a posto e a posto, sono stato messo fuori per un po '. Lavorando in de VS2017 IDE (Solution Explorer) avevo recentemente aggiunto / copiato un riferimento al file sorgente al mio progetto (ctrl-trascina) da un altro progetto. Esaminando le proprietà-> C / C ++ / Preprocessor - a livello di file sorgente, non a livello di progetto - ho notato che in una configurazione di rilascio è stato specificato _DEBUG invece di NDEBUG per questo file sorgente. Che era tutto il cambiamento necessario per sbarazzarsi del problema.


1

Il problema può essere risolto aggiungendo CRT di msvcrtd.lib nella libreria del linker. Poiché cryptlib.lib utilizzava la versione CRT di debug.

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.