'RuntimeLibrary' için Uyumsuzluk Algılandı


114

Crypto ++ 'yı C: \ cryptopp'a indirip çıkardım. İçindeki tüm projeleri (benioku'da belirtildiği gibi) oluşturmak için Visual Studio Express 2012'yi kullandım ve her şey başarıyla oluşturuldu. Sonra başka bir klasörde bir test projesi yaptım ve bağımlılık olarak cryptolib'i ekledim. Bundan sonra, tüm başlıkları kolayca dahil edebilmek için içerme yolunu ekledim. Derlemeye çalıştığımda çözülmemiş sembollerle ilgili bir hata aldım.

Bunu düzeltmek C:\cryptopp\Win32\Output\Debug\cryptlib.libiçin ek bağımlılıklar ekledim . Şimdi bu hatayı alıyorum:

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

Ayrıca şunu da anlıyorum:

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

Derlemeye çalıştığım kod basitti (bunu başka bir siteden aldım):

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

Bunu nasıl düzelteceğine dair bir fikrin var mı? Şu anda gerçekten sadece SHA-256'ya ihtiyacım var, başka bir şey yok. Windows 7 64 bit kullanıyorum ve bugün VS C ++ 'yı indirdim, bu yüzden en yeni sürüm olmalı.



1
Projemin çalışma zamanı kitaplığını Multi-threaded debug olarak ayarladım (crypto ++ 'da kullanılan ayardı) ve şimdi derliyor! :) Çok teşekkür ederim.
Momonga

Siz koşarken sorunlar çok daha erken ortaya çıktı VCUpgrade. Size Başarı olarak bildirilen VCUpgrade başarısızlığının belirtilerini görüyorsunuz .
jww

Yanıtlar:


234

(Bu zaten yorumlarda cevaplanmıştır, ancak gerçek bir cevabı olmadığı için bunu yazıyorum.)

Bu sorun, Visual C ++ 'ın daha yeni sürümlerinde ortaya çıkar (eski sürümler genellikle programı sessizce birbirine bağlar ve çalışma zamanında kilitlenir ve yanar). kendi programınızın içindeki dosyalar) CRT'nin (C RunTime kitaplığı) farklı sürümlerini kullanıyor.

Bu hatayı düzeltmek için, sizin Project Properties(ve / veya kullanmakta olduğunuz kitaplıkların) içine girip C/C++, sonra Code Generationve değerini kontrol etmeniz gerekir Runtime Library; bu , birbirine bağladığınız tüm dosyalar ve kitaplıklar için tamamen aynı olmalıdır . (Kurallar, DLL'lerle bağlantı kurmak için biraz daha rahattır, ancak burada "neden" bölümüne ve daha fazla ayrıntıya girmeyeceğim.)

Şu anda bu ayar için dört seçenek bulunmaktadır:

  1. Çok İş Parçacıklı Hata Ayıklama
  2. Çok iş parçacıklı hata ayıklama DLL'si
  3. Çok iş parçacıklı Yayın
  4. Çok iş parçacıklı Yayın DLL

Özel sorununuz, "Çok İş Parçacıklı Hata Ayıklama" (yani statik çok iş parçacıklı hata ayıklama CRT) ile oluşturulmuş bir kitaplığı, "Çok İş Parçacıklı Hata Ayıklama DLL " ayarı (yani dinamik çok iş parçacıklı hata ayıklama CRT'si) kullanılarak oluşturulan bir programa bağlamanızdan kaynaklanıyor gibi görünüyor . bu ayar ya kitaplıkta ya da programınızda. Şimdilik bunu programınızda değiştirmenizi öneriyorum.

Visual Studio projeleri, hata ayıklama ve yayın derlemeleri (ve 32/64-bit derlemeler) için farklı proje ayarları kümeleri kullandığından, ayarların tüm bu proje yapılandırmalarında eşleştiğinden emin olmanız gerektiğini unutmayın.

(Bazı) daha fazla bilgi için şunları görebilirsiniz (yukarıdaki bir yorumdan bağlantılı):

  1. MSDN'de Bağlayıcı Araçları Uyarısı LNK4098
  2. MSDN'de / MD, / ML, / MT, / LD (Çalışma Zamanı Kitaplığı Kullan)
  3. VC11 Beta ile hata oluşturma - MTd kitaplıklarını MDd exes ile karıştırmak Bugzilla @ Mozilla'da bağlantı kuramıyor

GÜNCELLEME : (Bu, bu kadar özen gösterilmesi gerektiğinin nedenini soran bir yoruma yanıttır.)

Birbirine bağladığımız iki kod parçası, standart kitaplığa bağlanıyor ve bu kitaplığı kullanıyorsa, iki kod parçamızın nasıl etkileşime girdiği ve verileri nasıl ilettiği konusunda büyük bir özen gösterilmedikçe, standart kitaplık her ikisi için de aynı olmalıdır . Genel olarak, hemen hemen tüm durumlarda, standart kitaplık çalışma zamanının tam olarak aynı sürümünü kullandığını söyleyebilirim (hata ayıklama / yayınlama, iş parçacıkları ve açıkça Visual C ++ sürümü, yineleyici hata ayıklama gibi diğer şeylerin yanı sıra)

Problemin en önemli kısmı şudur: bir fonksiyon çağrısının her iki tarafındaki nesnelerin boyutu hakkında aynı fikre sahip olmak .

Kod yukarıdaki iki adet dendiğini örneğin düşünün Ave B. A, standart kitaplığın bir sürümüne karşı ve B diğerine karşı derlenir . A'nın görüşüne göre, standart bir fonksiyonun kendisine döndürdüğü bazı rastgele nesneler (örneğin, bir bellek bloğu veya bir yineleyici veya bir FILEnesne veya her neyse) belirli bir boyuta ve düzene sahiptir (yapı düzeninin C / C ++.) Birkaç nedenden dolayı, B'nin aynı nesnelerin boyutu / düzeni hakkındaki fikri farklıdır (bu, ek hata ayıklama bilgileri, veri yapılarının zaman içindeki doğal gelişimi vb. Nedenlerle olabilir)

Şimdi, eğer A standart kitaplığı çağırır ve bir nesneyi geri alırsa, sonra o nesneyi B'ye geçirirse ve B o nesneye herhangi bir şekilde dokunursa, B nesneyi bozabilir (örneğin, yanlış alana yazabilir veya sonunu geçebilir) vb.)

Yukarıdakiler, olabilecek tek sorun türü değildir. Standart kitaplıktaki dahili global veya statik nesneler de sorunlara neden olabilir. Ve daha belirsiz sorun sınıfları da var.

Tüm bunlar, libs (statik çalışma zamanı kitaplığı) yerine DLL'leri (dinamik çalışma zamanı kitaplığı) kullanırken bazı açılardan daha tuhaf hale geliyor.

Bu durum, birlikte çalışan iki kod parçası tarafından kullanılan herhangi bir kitaplık için geçerli olabilir, ancak standart kitaplık çoğu (neredeyse tümü olmasa da) program tarafından kullanılır ve bu da çakışma olasılığını artırır.

Açıkladığım şey, kitaplık sürümlerini karıştırırsanız sizi bekleyen gerçek karmaşanın sulandırılmış ve basitleştirilmiş bir versiyonudur. Umarım bunu neden yapmamanız gerektiği konusunda size bir fikir verir!


Biraz kafam karıştı OP'ın hata olduğunu LNK2038 . Tüm kitaplıklarda olmadığı gibi, CRT aromalarını karıştırmayı imkansız kılan bazı CRT ayarlarına sahip Crypto ++ kemanlarından şüpheleniyorum - genellikle bu sadece bir uyarıdır (LNK4098) ve ne yaptığınızı biliyorsanız güvende olabilirsiniz (önerilmez, ancak sınırlamalarla mümkündür, bkz . stackoverflow.com/a/19944935/948581 ). Yine de Crypto ++ 'nın neden bu şekilde etkilendiğini bilmiyorum.

1
@Tibo: Bunlar DLL'ler için içe aktarım kitaplıkları değildir; Crypto ++ 'nın aslında buradaki programla statik olarak bağlantılı olduğuna inanıyorum. Bu, standart kitaplıkta bir modülde diğerine (muhtemelen) bağlanan herhangi bir uyumsuzluğun "Tek Tanım Kuralı" nı ihlal ettiği anlamına gelir. Hangi kötü. Bağlayıcı / kütüphaneci modülleri "etiketlemeye" başlayana kadar, bağlayıcı bunu algılayamadığı için (işlev / tür adları aynıydı, ancak gövdeleri ve tanımları önemli ölçüde farklıydı) bu bir hata değildi. yapının yapılandırması hakkında ekstra bilgilerle üretildi ...
yzt

@Tibo: ... (önceki yorumun devamı) Örneğin, OP'nin bildirdiği ilk hata bloğuna bakın. Orada, " RuntimeLibrary " Kripto ++ kütüphane ve OP'ın program için nesne dosyası hem bir etikettir ve değeri "dir MDd_DynamicDebug bunlardan biri ve" için " MTd_StaticDebug diğeri için". Bu şekilde, iki nesne dosyasını birbirine bağlamaya çalışan bağlayıcı, bu nesne dosyalarını üreten bağlayıcıların, özellikle ODR'yi potansiyel olarak ihlal edebilecek herhangi bir ayar olmak üzere, ilgili herhangi bir bilgi ile onları etiketlediği göz önüne alındığında, yepyeni bir hata sınıfını algılayabilir ve bildirebilir.
yzt

Seninle oldukça hemfikir olsam da, burada hala bir gizem alanı var. OP'nin sorununa gelince, sanırım Crypto ++ 'dan "dll.h" yi dahil ediyor ve ardından DLL'nin içe aktarma kitaplığı yerine statik kitaplığa bağlanmaya çalışıyor. Ama aynı hataları başka bir bilgisayarda değil bir bilgisayarda gördüm (VS2013 ultimate sp4 -> error, VS2013 community sp5 -> ok) ...

1
@yzt Bir çözüm buldum. / ZW swicth kullanmak yerine, Windows, WRL adlı bir sarmalayıcı kullanarak COM aracılığıyla WinRT API'sini kullanmanın bir yolunu sağlar. Sadece / ZW'yi kullanmamak, COM uygulama ayrıntılarını gizlediği için kodlamayı biraz zorlaştırır, ancak WinRT'yi / ZW olmadan kullanmak mümkündür.
Sahil Singh

3

Crypto ++ 'yı C: \ cryptopp'a indirip çıkardım. İçindeki tüm projeleri (benioku'da belirtildiği gibi) oluşturmak için Visual Studio Express 2012'yi kullandım ve her şey başarıyla oluşturuldu. Sonra başka bir klasörde bir test projesi yaptım ve bağımlılık olarak cryptolib'i ekledim.

Dönüşüm muhtemelen başarılı olmadı. Başarılı olan tek şey VCUpgrade çalıştırılmasıydı. Gerçek dönüşümün kendisi başarısız oldu, ancak gördüğünüz hataları deneyimleyene kadar bilemezsiniz. Bazı ayrıntılar için Crypto ++ wiki üzerinde Visual Studio konusuna bakın .


Bunu nasıl düzelteceğine dair bir fikrin var mı?

Sorunlarınızı çözmek için, vs2010.zipstatik C / C ++ çalışma zamanı bağlantısı ( /MTveya /MTd) vs2010-dynamic.zipistiyorsanız veya dinamik C / C ++ çalışma zamanı bağlantısı ( /MTveya /MTd) istiyorsanız indirmelisiniz . Her ikisi de VCUpgrade tarafından üretilen gizli, sessiz hataları düzeltir.


vs2010.zip, vs2010-dynamic.zipVe vs2005-dynamic.zipinşa edilmiştir son GitHub kaynaklardan . Bu yazı itibariyle (1 HAZİRAN 2016), bu etkili bir şekilde Crypto ++ 5.6.4 öncesi. ZIP dosyalarını 5.6.2 veya 5.6.3 gibi alt düzey Crypto ++ ile kullanıyorsanız, küçük problemlerle karşılaşırsınız.

Farkında olduğum iki küçük sorun var. İlk bir adlandırma olduğu bench.cppiçinbench1.cpp . Hata şudur:

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

Düzeltme, (1) cryptest.vcxprojnot defterinde açmak , bulmak bench1.cppve sonra olarak yeniden adlandırmaktır bench.cpp. Veya (2) Yeniden adlandırma bench.cppiçin bench1.cppdosya sisteminde. Lütfen bu dosyayı silmeyin.

İkinci sorun biraz daha karmaşık çünkü hareketli bir hedef. 5.6.2 veya 5.6.3 gibi alt düzey sürümlerde GitHub'da bulunan en son sınıflar eksik . Eksik sınıf dosyaları arasında HKDF (5.6.3), RDRAND (5.6.3), RDSEED (5.6.3), ChaCha (5.6.4), BLAKE2 (5.6.4), Poly1305 (5.6.4) vb. Bulunur.

Düzeltme, eksik kaynak dosyalarını alt düzey sürümler için mevcut olmadıklarından Visual Studio proje dosyalarından kaldırmaktır.

Diğer bir seçenek de eksik sınıf dosyalarını en son kaynaklardan eklemektir, ancak bazı zorluklar olabilir. Örneğin, kaynakların birçoğu kurnazca son bağlıdır config.h, cpu.hve cpu.cpp. "İncelik", düşük performans gösteren bir ders aldığınızı fark etmeyeceğinizdir.

Düşük performans gösteren sınıfa bir örnek BLAKE2'dir. config.hderleme zamanı ARM-32 ve ARM-64 algılama ekler. cpu.hve cpu.cppderleme zamanı algılamasına bağlı olan çalışma zamanı ARM talimat algılamasını ekler. BLAKE2'yi diğer dosyalar olmadan eklerseniz, hiçbir algılama gerçekleşmez ve düz bir C / C ++ uygulaması elde edersiniz. Vanilya C / C ++ için bayt başına 40 döngü ve bayt başına yaklaşık 9 ila 12 döngü çalışan NEON fırsatını kaçırdığınızı muhtemelen fark etmeyeceksiniz.


Cryptopp wiki'deki talimatları izledim, vs2010-dynamic.zip'i indirdim ve içeriğini cryptopp563 koduna yapıştırdım. Oluşturulmuş ve bazı kaynak dosyaları eksik. Sorun değil wiki, zip dosyasının github'daki en son proje için olduğunu söylüyor ve sadece eksik dosyaları silin. Silindi. Artık proje sadece şunları oluşturmuyor: 4 bağlantı hatası, bir örnek: hata LNK2001: çözülmemiş harici sembol "void __cdecl OutputResultOperations (char const *, char const *, bool, unsigned long, double)" (? OutputResultOperations @@ YAXPBD0_NKN @ Z)
Yaniv

Projede eksik olan bir bench.cpp olduğu ortaya çıktı. Ama ondan sonra bile bu düzeltmeyi fiptest.cpp'ye uygulayana kadar derlenmedi github.com/weidai11/cryptopp/pull/151/files?diff=split Keşke proje zip dosyalarını eklemek gibi bu konuda bir düzen verselerdi git falan. Ve evet, derleyicimin VS2015 güncellemesi 2 olduğunu söylemeyi ihmal ettim. Sonuç olarak, yazdığım ipuçlarını takip edin ve işe yarıyor.
Yaniv

@Yaniv - İlk yorum için, diğer kullanıcıların sorun yaşamaması için ne önerirsiniz? İkinci yorum için, tamamen test edildikten sonra yamayı almayı planlıyoruz. Bu arada yapabileceğimiz bir şey var mı? (Bu yanıta ek bilgi ekledim, ancak kullanıcıların sorun yaşamadığından emin olmak istiyorum).
jww

Öncelikle bunu yaptığınız için çok teşekkürler. Crypto ++ gerçekten harika. Derleme problemleriyle ilgili olarak, windows sln ve proje dosyalarını projedeki en son dosyalarla uyumlu tutmaya çalışın ve bu değişiklikler elbette ki, bu pencereler bir şekilde kod tabanına bağlanmalı ve hatta kaynak ağacında olmalıdır. Bu çok fazlaysa, en azından görsel stüdyo oluşturma ortamına sahip zip dosyasının mevcut kararlı resmi sürümle uyumlu olduğundan emin olun.
Yaniv

Fiptest.cpp için yama ile ilgili olarak - VS2015 ile ilgili farklı bir şey görünüyor, bu yüzden VS2015'i kullanmak isteyen herkesin bu yamayı uygulaması gerektiğini tahmin ediyorum. Bu, VS2015 için doğru hata ayıklama geri çağrısını tanımlayan bir #ifdef bloğundaki başka bir durumdur ve manuel olarak yama yapmak gerçekten çok kolaydır.
Yaniv

3

ITERATOR_DEBUG_LEVEL'deki uyumsuzlukla birlikte bu sorunu yaşadım. Pazar akşamı problemi her şeye rağmen iyi ve gitmek için iyi göründüğü için, bir süre dışarıda kaldım. VS2017 IDE'de (Çözüm Gezgini) Çalışma Son zamanlarda projeme başka bir projeden (ctrl-sürükleme) bir kaynak dosyası başvurusu ekledim / kopyaladım. Özellikler -> C / C ++ / Önişlemci - proje düzeyinde değil, kaynak dosya düzeyinde - baktığımda, bir Yayın yapılandırmasında bu kaynak dosya için NDEBUG yerine _DEBUG belirtildiğini fark ettim. Problemden kurtulmak için gereken tüm değişiklik buydu.


1

Bağlayıcı kitaplığına msvcrtd.lib'in CRT'si eklenerek sorun çözülebilir. Çünkü cryptlib.lib, hata ayıklamanın CRT sürümünü kullandı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.