Wykryto niezgodność dla „RuntimeLibrary”

114

Pobrałem i rozpakowałem Crypto ++ w C: \ cryptopp. Użyłem Visual Studio Express 2012 do zbudowania wszystkich projektów w środku (zgodnie z instrukcją w pliku Readme) i wszystko zostało pomyślnie zbudowane. Następnie wykonałem projekt testowy w innym folderze i dodałem cryptolib jako zależność. Następnie dodałem ścieżkę dołączania, aby móc łatwo dołączyć wszystkie nagłówki. Kiedy próbowałem skompilować, pojawił się błąd dotyczący nierozwiązanych symboli.

Aby temu zaradzić, dodałem C:\cryptopp\Win32\Output\Debug\cryptlib.libdo linku dodatkowe zależności. Teraz pojawia się ten błąd:

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

Dostaję też:

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

Kod, który próbowałem skompilować, był prosty (otrzymałem go z innej witryny):

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

Jakieś pomysły, jak to naprawić? Naprawdę potrzebuję teraz tylko SHA-256, nic więcej. Używam 64-bitowego systemu Windows 7, a dzisiaj pobrałem VS C ++, więc powinna to być najnowsza wersja.

Momonga
źródło
1
Ustawiłem bibliotekę wykonawczą mojego projektu na debugowanie wielowątkowe (było to ustawienie używane w crypto ++) i teraz się kompiluje! :) Dziękuję bardzo.
Momonga,
Problemy pojawiły się znacznie wcześniej, kiedy biegałeś VCUpgrade. Widzisz objawy niepowodzenia VCUpgrade, które zostało zgłoszone jako Sukces .
jww

Odpowiedzi:

234

(Odpowiedź na to jest już w komentarzach, ale ponieważ nie ma na to rzeczywistej odpowiedzi , piszę to.)

Ten problem pojawia się w nowszych wersjach Visual C ++ (starsze wersje zwykle po prostu dyskretnie łączyły program, który powodował awarię i nagrywanie w czasie wykonywania). Oznacza to, że niektóre biblioteki, które łączysz ze swoim programem (lub nawet niektóre źródła pliki wewnątrz samego programu) używają różnych wersji CRT (biblioteki C RunTime).

Aby poprawić ten błąd, musisz przejść do swojej Project Properties(i / lub bibliotek, z których korzystasz), a następnie do C/C++, następnie Code Generationi sprawdzić wartość Runtime Library; powinno to być dokładnie takie samo dla wszystkich plików i bibliotek, które łączysz razem. (Zasady są nieco bardziej rozluźnione w przypadku łączenia z bibliotekami DLL, ale nie zamierzam tutaj zagłębiać się w „dlaczego” i więcej szczegółów).

Obecnie dostępne są cztery opcje tego ustawienia:

  1. Debugowanie wielowątkowe
  2. Wielowątkowa biblioteka DLL debugowania
  3. Wydanie wielowątkowe
  4. Biblioteka DLL wydania wielowątkowego

Twój szczególny problem wydaje się wynikać z połączenia biblioteki zbudowanej przy użyciu funkcji „Multithreaded Debug” (tj. Statycznego, wielowątkowego debugowania CRT) z programem, który jest budowany przy użyciu ustawienia „Multithreaded Debug DLL ” (tj. Dynamiczny wielowątkowy debug CRT). Należy zmienić to ustawienie w bibliotece lub w programie. Na razie proponuję zmienić to w swoim programie.

Należy pamiętać, że ponieważ projekty programu Visual Studio używają różnych zestawów ustawień projektu dla kompilacji debugowania i wydania (oraz kompilacji 32/64-bitowych), należy upewnić się, że ustawienia są zgodne we wszystkich tych konfiguracjach projektu.

Aby uzyskać (trochę) więcej informacji, możesz zobaczyć te (link z komentarza powyżej):

  1. Ostrzeżenie narzędzi konsolidatora LNK4098 w witrynie MSDN
  2. / MD, / ML, / MT, / LD (Użyj biblioteki wykonawczej ) w witrynie MSDN
  3. Twórz błędy za pomocą VC11 Beta - mieszanie bibliotek MTd z plikami exes MDd nie łączy się z Bugzilla @ Mozilla

AKTUALIZACJA : (jest to odpowiedź na komentarz, w którym prosi się o powód, dla którego należy zachować taką ostrożność).

Jeśli dwa fragmenty kodu, które łączymy ze sobą, same łączą się z biblioteką standardową i korzystają z niej, to biblioteka standardowa musi być taka sama dla obu z nich, chyba że przywiązuje się dużą wagę do tego, jak nasze dwa fragmenty kodu współdziałają i przekazują dane. Generalnie powiedziałbym, że w prawie wszystkich sytuacjach po prostu użyj dokładnie tej samej wersji standardowego środowiska uruchomieniowego biblioteki (dotyczy to debugowania / wydania, wątków i oczywiście wersji Visual C ++, między innymi debugowania iteratora itp.)

Najważniejsza część problemu polega na tym, że mamy ten sam pomysł na temat rozmiaru obiektów po obu stronach wywołania funkcji .

Weźmy na przykład pod uwagę, że powyższe dwa fragmenty kodu nazywają się Ai B. A jest kompilowany na jednej wersji biblioteki standardowej, a B na innej. Z punktu widzenia A, jakiś losowy obiekt, który zwraca do niego standardowa funkcja (np. Blok pamięci, iterator, FILEobiekt lub cokolwiek innego) ma określony rozmiar i układ (pamiętaj, że układ struktury jest określany i ustalany w czasie kompilacji w C / C ++.) Z kilku powodów koncepcja B dotycząca rozmiaru / układu tych samych obiektów jest inna (może to być spowodowane dodatkowymi informacjami debugowania, naturalną ewolucją struktur danych w czasie itp.)

Teraz, jeśli A wywołuje bibliotekę standardową i pobiera obiekt z powrotem, a następnie przekazuje ten obiekt do B, a B dotyka tego obiektu w jakikolwiek sposób, są szanse, że B zepsuje ten obiekt (np. Zapisze niewłaściwe pole lub przekroczy koniec tego itp.)

To nie jedyny rodzaj problemów, które mogą się zdarzyć. Wewnętrzne globalne lub statyczne obiekty w bibliotece standardowej również mogą powodować problemy. Są też bardziej niejasne klasy problemów.

Wszystko to staje się dziwniejsze w niektórych aspektach, gdy używa się bibliotek DLL (dynamicznej biblioteki wykonawczej) zamiast bibliotek (statyczna biblioteka uruchomieniowa).

Ta sytuacja może dotyczyć dowolnej biblioteki używanej przez dwa fragmenty kodu, które współpracują ze sobą, ale biblioteka standardowa jest używana przez większość (jeśli nie prawie wszystkie) programy, co zwiększa ryzyko kolizji.

To, co opisałem, jest oczywiście rozwodnioną i uproszczoną wersją rzeczywistego bałaganu, który czeka na ciebie, jeśli zmiksujesz wersje biblioteki. Mam nadzieję, że podpowie Ci, dlaczego nie powinieneś tego robić!

yzt
źródło
Jestem trochę zmieszany. Błąd OP to LNK2038 . Jak się nie dzieje ze wszystkimi bibliotekami, podejrzewam skrzypce Crypto ++ z niektórych ustawień CRT, które sprawiają, że niemożliwe, aby mieszać smaki CRT - zwykle jest to tylko ostrzeżenie (LNK4098) i może być bezpieczne, jeśli wiesz co robisz (nie zalecane, ale możliwe z ograniczeniami, patrz np. stackoverflow.com/a/19944935/948581 ). Nie wiem jednak, dlaczego wpływa to na Crypto ++ w ten sposób.
1
@Tibo: To nie są biblioteki importu dla bibliotek DLL; Uważam, że Crypto ++ jest w rzeczywistości łączony statycznie z programem tutaj. Oznacza to, że jakakolwiek niezgodność w standardowej bibliotece połączonej w jednym module z innym (prawdopodobnie) narusza „jedną regułę definicji”. Co jest złe. Kiedyś nie był to błąd, ponieważ linker nie był nawet w stanie tego wykryć (nazwy funkcji / typów były takie same, ale ich ciała i definicje znacznie się różniły) aż do VC10, kiedy linker / bibliotekarz zaczął "tagować" moduły wygenerował dodatkowe informacje o konfiguracji kompilacji ...
yzt
@Tibo: ... (kontynuacja z poprzedniego komentarza) Na przykład spójrz na pierwszy blok błędów zgłaszanych przez PO. Tam „ RuntimeLibrary ” jest znacznikiem zarówno w bibliotece Crypto ++, jak iw pliku obiektowym programu OP, a jego wartość to „ MDd_DynamicDebug ” dla jednego z nich i „ MTd_StaticDebug ” dla drugiego. W ten sposób konsolidator, który próbuje połączyć ze sobą dwa pliki obiektowe, może wykryć i zgłosić zupełnie nową klasę błędów, biorąc pod uwagę, że konsolidatorzy, którzy utworzyli te pliki obiektowe, oznaczyli je wszelkimi istotnymi informacjami, szczególnie ustawieniami, które potencjalnie naruszałyby ODR.
yzt
Chociaż całkowicie się z tobą zgadzam, nadal istnieje tu obszar tajemnic. Jeśli chodzi o problem OP, myślę, że dołącza on „dll.h” z Crypto ++, a następnie próbuje połączyć się z biblioteką statyczną zamiast biblioteki importu DLL. Ale widziałem dokładnie te same błędy na jednym komputerze, a nie na innym (VS2013 ultimate sp4 -> błąd, społeczność VS2013 sp5 -> ok) ...
1
@yzt Znalazłem rozwiązanie. Zamiast używać / ZW swicth, system Windows zapewnia sposób korzystania z interfejsu API WinRT przez COM przy użyciu opakowania o nazwie WRL. Chodzi o to, że brak / ZW utrudnia kodowanie, ponieważ ukrywa szczegóły implementacji COM, ale możliwe jest użycie WinRT bez / ZW.
Sahil Singh
3

Pobrałem i rozpakowałem Crypto ++ w C: \ cryptopp. Użyłem Visual Studio Express 2012 do zbudowania wszystkich projektów w środku (zgodnie z instrukcją w pliku Readme) i wszystko zostało pomyślnie zbudowane. Następnie wykonałem projekt testowy w innym folderze i dodałem cryptolib jako zależność.

Konwersja prawdopodobnie się nie powiodła. Jedyną rzeczą, która się powiodła, było uruchomienie VCUpgrade. Sama konwersja nie powiodła się, ale nie wiesz, dopóki nie napotkasz błędów, które widzisz. Aby uzyskać szczegółowe informacje, zobacz Visual Studio w witrynie wiki Crypto ++.


Jakieś pomysły, jak to naprawić?

Aby rozwiązać problemy, pobierz, vs2010.zipjeśli chcesz statyczne łączenie środowiska wykonawczego C / C ++ ( /MTlub /MTd) lub vs2010-dynamic.zipjeśli chcesz dynamiczne łączenie środowiska wykonawczego C / C ++ ( /MTlub /MTd). Obie naprawiają ukryte, ciche awarie generowane przez VCUpgrade.


vs2010.zip, vs2010-dynamic.zipi vs2005-dynamic.zipsą zbudowane z najnowszych źródeł GitHub . W chwili pisania tego tekstu (1 czerwca 2016 r.) Jest to faktycznie wersja sprzed Crypto ++ 5.6.4. Jeśli używasz plików ZIP z niższym poziomem Crypto ++, takim jak 5.6.2 lub 5.6.3, napotkasz drobne problemy.

Zdaję sobie sprawę z dwóch drobnych problemów. Pierwsza to zmiana nazwy bench.cppnabench1.cpp . Jego błąd to:

  • 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)

Rozwiązanie polega na (1) otwarciu cryptest.vcxprojw notatniku, znalezieniu bench1.cpp, a następnie zmianie nazwy na bench.cpp. Lub (2) Zmień nazwę bench.cpp, aby bench1.cppw systemie plików. Proszę nie usuwać tego pliku.

Drugi problem jest trochę trudniejszy, ponieważ jest to ruchomy cel. W wersjach niższych poziomów, takich jak 5.6.2 lub 5.6.3, brakuje najnowszych klas dostępnych w GitHub . Brakujące pliki klas obejmują HKDF (5.6.3), RDRAND (5.6.3), RDSEED (5.6.3), ChaCha (5.6.4), BLAKE2 (5.6.4), Poly1305 (5.6.4) itd.

Poprawka polega na usunięciu brakujących plików źródłowych z plików projektu programu Visual Studio, ponieważ nie istnieją one dla wersji niższego poziomu.

Inną opcją jest dodanie brakujących plików klas z najnowszych źródeł, ale mogą wystąpić komplikacje. Na przykład, wiele źródeł subtelnie zależeć ostatni config.h, cpu.hi cpu.cpp. „Subtelność” polega na tym, że nie zdasz sobie sprawy, że masz słabą klasę.

Przykładem klasy o słabych wynikach jest BLAKE2. config.hdodaje czas kompilacji wykrywania ARM-32 i ARM-64. cpu.hi cpu.cppdodaje wykrywanie instrukcji ARM w czasie wykonywania, które zależy od wykrywania czasu kompilacji. Jeśli dodasz BLAKE2 bez innych plików, żadne wykrycie nie nastąpi i otrzymasz prostą implementację C / C ++. Prawdopodobnie nie zdasz sobie sprawy, że tracisz szansę na NEON, która działa od 9 do 12 cykli na bajt w porównaniu do około 40 cykli na bajt w waniliowym C / C ++.

jww
źródło
Postępowałem zgodnie z instrukcjami na wiki cryptopp, pobrałem plik vs2010-dynamic.zip i wkleiłem jego zawartość do kodu cryptopp563. Zbudowano i brakuje niektórych plików źródłowych. Żaden problem, według wiki, plik zip dotyczy najnowszego projektu na github i po prostu usuń wszystkie brakujące pliki. Usunięto. Teraz projekt po prostu się nie buduje: 4 błędy łącza, jeden przykład: błąd LNK2001: nierozwiązany symbol zewnętrzny "void __cdecl OutputResultOperations (char const *, char const *, bool, unsigned long, double)" (? OutputResultOperations @@ YAXPBD0_NKN @ Z)
Janów
Okazało się, że w projekcie brakowało pliku bench.cpp. Ale nawet po tym nie skompilował się, dopóki nie zastosowałem tej poprawki do fiptest.cpp github.com/weidai11/cryptopp/pull/151/files?diff=split Chciałbym, żeby zrobili w tym jakąś kolejność, na przykład dodając pliki zip projektu w gita czy coś. I tak, zapomniałem powiedzieć, że mój kompilator to VS2015 aktualizacja 2. Podsumowując, postępuj zgodnie ze wskazówkami, które napisałem i działa.
Janów
@Yaniv - Jako pierwszy komentarz, co radzisz, aby inni użytkownicy nie mieli problemów? Jeśli chodzi o drugi komentarz, planujemy zabrać łatkę, gdy tylko ją w pełni przetestujemy. Czy w międzyczasie możemy coś zrobić? (Dodałem dodatkowe informacje do tej odpowiedzi, ale chcę mieć pewność, że użytkownicy nie będą mieli problemów).
jww
Po pierwsze, bardzo dziękuję za to. Crypto ++ naprawdę rządzi. Jeśli chodzi o problemy z kompilacją, staraj się, aby sln systemu Windows i pliki projektu były zgodne z najnowszymi plikami w projekcie, a ponieważ te zmiany oczywiście, te kompilacje okna powinny być w jakiś sposób połączone z bazą kodu, a może nawet znajdować się w drzewie źródłowym. Jeśli to za dużo, przynajmniej upewnij się, że plik zip ze środowiskiem kompilacji Visual Studio jest zgodny z aktualną stabilną oficjalną wersją.
Yaniv
Odnośnie łatki do fiptest.cpp - wydaje się, że w VS2015 jest coś innego, więc myślę, że każdy, kto chce używać VS2015, musi ją zastosować. To tylko kolejny przypadek w bloku #ifdef, który wydaje się definiować właściwe wywołanie zwrotne debugowania dla VS2015, a łatwa ręczna jest naprawdę łatwa.
Janów
3

Miałem ten problem wraz z niedopasowaniem w ITERATOR_DEBUG_LEVEL. Ponieważ problem z niedzielnym wieczorem wydawał mi się w porządku i dobrze się bawić, na jakiś czas zostałem wyrzucony. Pracując w de VS2017 IDE (Solution Explorer) Niedawno dodałem / skopiowałem odniesienie do pliku źródłowego do mojego projektu (ctrl-drag) z innego projektu. Patrząc na właściwości-> C / C ++ / Preprocessor - na poziomie pliku źródłowego, a nie na poziomie projektu - zauważyłem, że w konfiguracji wydania podano _DEBUG zamiast NDEBUG dla tego pliku źródłowego. To była jedyna zmiana potrzebna do pozbycia się problemu.

Jan
źródło
1

Problem można rozwiązać, dodając CRT pliku msvcrtd.lib w bibliotece konsolidatora. Ponieważ cryptlib.lib używał wersji debugowania CRT.

abhijithkp
źródło