Ketidakcocokan Terdeteksi untuk 'RuntimeLibrary'


114

Saya mengunduh dan mengekstrak Crypto ++ di C: \ cryptopp. Saya menggunakan Visual Studio Express 2012 untuk membangun semua proyek di dalamnya (seperti yang diinstruksikan dalam readme), dan semuanya berhasil dibangun. Kemudian saya membuat proyek uji di beberapa folder lain dan menambahkan cryptolib sebagai dependensi. Setelah itu, saya menambahkan jalur penyertaan sehingga saya dapat dengan mudah menyertakan semua header. Ketika saya mencoba mengompilasi, saya mendapat kesalahan tentang simbol yang belum terselesaikan.

Untuk mengatasinya, saya menambahkan C:\cryptopp\Win32\Output\Debug\cryptlib.libke link dependensi tambahan. Sekarang saya mendapatkan kesalahan ini:

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

Saya juga mendapatkan:

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

Kode yang saya coba kompilasi sederhana (saya mendapatkannya dari situs lain):

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

Ada ide bagaimana cara memperbaikinya? Saya benar-benar hanya membutuhkan SHA-256 sekarang, tidak ada yang lain. Saya menggunakan Windows 7 64 bit, dan saya mengunduh VS C ++ hari ini, jadi ini harus versi terbaru.



1
Saya mengatur pustaka runtime proyek saya ke Multi-threaded debug (itu adalah pengaturan yang digunakan dalam crypto ++) dan sekarang dikompilasi! :) Terima kasih banyak.
Momonga

Masalah terjadi jauh lebih awal saat Anda berlari VCUpgrade. Anda melihat gejala kegagalan VCUpgrade yang dilaporkan sebagai Berhasil kepada Anda.
jww

Jawaban:


233

(Ini sudah dijawab dalam komentar, tetapi karena tidak ada jawaban yang sebenarnya , saya menulis ini.)

Masalah ini muncul dalam versi Visual C ++ yang lebih baru (versi yang lebih lama biasanya hanya menautkan program secara diam-diam dan akan macet dan terbakar pada saat dijalankan.) Ini berarti bahwa beberapa pustaka yang Anda tautkan dengan program Anda (atau bahkan beberapa sumber file di dalam program Anda sendiri) menggunakan versi CRT yang berbeda (perpustakaan C RunTime.)

Untuk memperbaiki kesalahan ini, Anda perlu masuk ke Anda Project Properties(dan / atau perpustakaan yang Anda gunakan,) lalu ke C/C++, lalu Code Generation, dan periksa nilai Runtime Library; ini harus persis sama untuk semua file dan pustaka yang Anda tautkan. (Aturannya sedikit lebih santai untuk menghubungkan dengan DLL, tetapi saya tidak akan membahas "mengapa" dan lebih detail di sini.)

Saat ini ada empat opsi untuk pengaturan ini:

  1. Debug Multithread
  2. DLL Debug Multithreaded
  3. Rilis Multithreaded
  4. Rilis Multithreaded DLL

Masalah khusus Anda tampaknya berasal dari Anda menautkan pustaka yang dibangun dengan "Multithreaded Debug" (yaitu CRT debug multithread statis) terhadap program yang sedang dibangun menggunakan setelan "Multithreaded Debug DLL " (yaitu CRT debug multithread dinamis.) Anda harus mengubah pengaturan ini baik di perpustakaan, atau di program Anda. Untuk saat ini, saya sarankan mengubah ini di program Anda.

Perhatikan bahwa karena proyek Visual Studio menggunakan set yang berbeda dari pengaturan proyek untuk debug dan rilis build (dan 32/64-bit build), Anda harus memastikan pengaturan cocok di semua konfigurasi proyek ini.

Untuk (beberapa) informasi lebih lanjut, Anda dapat melihat ini (ditautkan dari komentar di atas):

  1. Linker Tools Warning LNK4098 di MSDN
  2. / MD, / ML, / MT, / LD (Gunakan Run-Time Library) di MSDN
  3. Buat kesalahan dengan VC11 Beta - pencampuran MTd libs dengan MDd exes gagal ditautkan ke Bugzilla @ Mozilla

PEMBARUAN : (Ini adalah tanggapan atas komentar yang menanyakan alasan mengapa banyak perawatan ini harus dilakukan.)

Jika dua bagian kode yang kita tautkan bersama-sama tertaut dan menggunakan pustaka standar, maka pustaka standar harus sama untuk keduanya, kecuali jika perhatian besar diberikan tentang bagaimana dua bagian kode kita berinteraksi dan menyebarkan data. Secara umum, saya akan mengatakan bahwa untuk hampir semua situasi cukup gunakan versi yang sama persis dari runtime perpustakaan standar (mengenai debug / rilis, utas, dan jelas versi Visual C ++, antara lain seperti debugging iterator, dll.)

Bagian terpenting dari masalahnya adalah ini: memiliki gagasan yang sama tentang ukuran objek di kedua sisi pemanggilan fungsi .

Pertimbangkan misalnya bahwa dua bagian kode di atas disebut Adan B. A dikompilasi terhadap satu versi pustaka standar, dan B terhadap versi lainnya. Dalam pandangan A, beberapa objek acak yang dikembalikan oleh fungsi standar (misalnya blok memori atau iterator atau FILEobjek atau apa pun) memiliki ukuran dan tata letak tertentu (ingat bahwa tata letak struktur ditentukan dan diperbaiki pada waktu kompilasi di C / C ++.) Untuk beberapa alasan, gagasan B tentang ukuran / tata letak objek yang sama berbeda (bisa jadi karena informasi debug tambahan, evolusi alami struktur data dari waktu ke waktu, dll.)

Sekarang, jika A memanggil pustaka standar dan mendapatkan sebuah objek kembali, lalu meneruskan objek itu ke B, dan B menyentuh objek itu dengan cara apa pun, kemungkinan B akan mengacaukan objek itu (misalnya menulis bidang yang salah, atau melewati ujungnya dari itu, dll.)

Hal di atas bukanlah satu-satunya jenis masalah yang dapat terjadi. Objek global atau statis internal di pustaka standar juga dapat menyebabkan masalah. Dan ada juga kelas masalah yang lebih tidak jelas.

Semua ini menjadi lebih aneh dalam beberapa aspek saat menggunakan DLL (pustaka runtime dinamis) daripada libs (pustaka runtime statis.)

Situasi ini dapat diterapkan ke pustaka apa pun yang digunakan oleh dua bagian kode yang bekerja bersama, tetapi pustaka standar digunakan oleh sebagian besar (jika tidak hampir semua) program, dan itu meningkatkan kemungkinan bentrokan.

Apa yang saya jelaskan jelas merupakan versi yang dipermudah dan disederhanakan dari kekacauan sebenarnya yang menanti Anda jika Anda mencampur versi perpustakaan. Saya harap ini memberi Anda gambaran tentang mengapa Anda tidak boleh melakukannya!


Saya sedikit bingung. Kesalahan OP adalah LNK2038 . Karena tidak terjadi dengan semua lib, saya menduga Crypto ++ fiddles dengan beberapa pengaturan CRT yang membuatnya tidak mungkin untuk mencampur rasa CRT - biasanya itu hanya peringatan (LNK4098) dan Anda mungkin aman jika Anda tahu apa yang Anda lakukan (tidak disarankan, tetapi mungkin dengan batasan, lihat misalnya stackoverflow.com/a/19944935/948581 ). Saya tidak tahu mengapa Crypto ++ terpengaruh seperti ini.

1
@Tibo: Ini bukan pustaka impor untuk DLL; Saya yakin Crypto ++ sebenarnya sedang ditautkan secara statis dengan program di sini. Ini berarti bahwa setiap ketidakcocokan dalam pustaka standar yang ditautkan dalam satu modul dengan modul lainnya (mungkin) melanggar "Aturan Satu Definisi". Itu buruk. Ini dulunya bukan error, karena linker bahkan tidak dapat mendeteksi ini (nama fungsi / jenisnya sama, tetapi badan dan definisinya berbeda secara signifikan) hingga VC10 ketika linker / librarian mulai "menandai" modul itu diproduksi dengan informasi tambahan tentang konfigurasi build ...
yzt

@Tibo: ... (lanjutan dari komentar sebelumnya) Misalnya, lihat blok kesalahan pertama yang dilaporkan OP. Di sana, " RuntimeLibrary " adalah tag pada pustaka Crypto ++ dan file objek untuk program OP, dan nilainya adalah " MDd_DynamicDebug " untuk salah satunya dan " MTd_StaticDebug " untuk yang lainnya. Dengan cara ini, penaut yang mencoba menautkan dua file objek bersama-sama dapat mendeteksi dan melaporkan kelas kesalahan yang sama sekali baru, mengingat bahwa penaut yang menghasilkan file objek tersebut menandai mereka dengan informasi yang relevan, terutama pengaturan apa pun yang berpotensi melanggar ODR.
yzt

Meskipun saya setuju dengan Anda, masih ada area misteri di sini. Adapun masalah OP, saya kira dia termasuk "dll.h" dari Crypto ++, dan kemudian mencoba untuk menautkan ke lib statis alih-alih pustaka impor DLL. Tapi saya telah melihat kesalahan yang sama persis di satu komputer, bukan di komputer lain (VS2013 ultimate sp4 -> error, VS2013 community sp5 -> ok) ...

1
@yzt Saya menemukan solusi. Alih-alih menggunakan / ZW swicth, windows menyediakan cara untuk menggunakan WinRT API melalui COM menggunakan pembungkus yang disebut WRL. Hanya saja tidak menggunakan / ZW membuat pengkodean sedikit sulit karena menyembunyikan detail implementasi COM, tetapi sangat mungkin untuk menggunakan WinRT tanpa / ZW.
Sahil Singh

3

Saya mengunduh dan mengekstrak Crypto ++ di C: \ cryptopp. Saya menggunakan Visual Studio Express 2012 untuk membangun semua proyek di dalamnya (seperti yang diinstruksikan dalam readme), dan semuanya berhasil dibangun. Kemudian saya membuat proyek uji di beberapa folder lain dan menambahkan cryptolib sebagai dependensi.

Konversi tersebut mungkin tidak berhasil. Satu-satunya hal yang berhasil adalah menjalankan VCUpgrade. Konversi yang sebenarnya sendiri gagal tetapi Anda tidak tahu sampai Anda mengalami kesalahan yang Anda lihat. Untuk beberapa detail, lihat Visual Studio di Crypto ++ wiki.


Ada ide bagaimana cara memperbaikinya?

Untuk mengatasi masalah Anda, Anda harus mendownload vs2010.zipjika Anda menginginkan penautan runtime C / C ++ statis ( /MTatau /MTd), atau vs2010-dynamic.zipjika Anda ingin penautan waktu proses C / C ++ dinamis ( /MTatau /MTd). Keduanya memperbaiki kegagalan tersembunyi dan laten yang dihasilkan oleh VCUpgrade.


vs2010.zip, vs2010-dynamic.zipdan vs2005-dynamic.zipdibuat dari sumber GitHub terbaru . Pada tulisan ini (1 JUN 2016), itu efektif sebelum Crypto ++ 5.6.4. Jika Anda menggunakan file ZIP dengan Crypto ++ level bawah, seperti 5.6.2 atau 5.6.3, Anda akan mengalami masalah kecil.

Ada dua masalah kecil yang saya sadari. Pertama adalah mengganti nama bench.cppmenjadibench1.cpp . Kesalahannya adalah:

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

Cara mengatasinya adalah (1) buka cryptest.vcxprojdi notepad, temukan bench1.cpp, lalu ganti namanya menjadi bench.cpp. Atau (2) ubah nama bench.cppmenjadi bench1.cpppada sistem file. Tolong jangan hapus file ini.

Masalah kedua sedikit lebih rumit karena ini adalah target yang bergerak. Rilis level bawah, seperti 5.6.2 atau 5.6.3, tidak memiliki kelas terbaru yang tersedia di GitHub . File kelas yang hilang termasuk HKDF (5.6.3), RDRAND (5.6.3), RDSEED (5.6.3), ChaCha (5.6.4), BLAKE2 (5.6.4), Poly1305 (5.6.4), dll.

Perbaikannya adalah menghapus file sumber yang hilang dari file proyek Visual Studio karena tidak ada untuk rilis tingkat bawah.

Opsi lainnya adalah menambahkan file kelas yang hilang dari sumber terbaru, tetapi mungkin ada komplikasi. Misalnya, banyak sumber yang secara halus bergantung pada yang terbaru config.h, cpu.hdan cpu.cpp. Yang "halus" adalah Anda tidak akan menyadari bahwa Anda mendapatkan kelas yang berkinerja rendah.

Contoh kelas berkinerja rendah adalah BLAKE2. config.hmenambahkan waktu kompilasi deteksi ARM-32 dan ARM-64. cpu.hdan cpu.cppmenambahkan deteksi instruksi ARM runtime, yang bergantung pada deteksi waktu kompilasi. Jika Anda menambahkan BLAKE2 tanpa file lain, maka tidak ada pendeteksian yang terjadi dan Anda mendapatkan implementasi C / C ++ langsung. Anda mungkin tidak akan menyadari bahwa Anda kehilangan peluang NEON, yang berjalan sekitar 9 hingga 12 siklus per byte versus 40 siklus per byte atau lebih untuk vanilla C / C ++.


Saya mengikuti instruksi di wiki cryptopp, mengunduh vs2010-dynamic.zip dan menempelkan isinya ke kode cryptopp563. Dibangun dan beberapa file sumber hilang. Tidak masalah, wiki mengatakan zip untuk proyek terbaru di github, dan hapus saja semua file yang hilang. Dihapus. Sekarang proyek tersebut tidak membangun: 4 kesalahan tautan, satu contoh: kesalahan LNK2001: simbol eksternal yang belum terselesaikan "void __cdecl OutputResultOperations (char const *, char const *, bool, unsigned long, double)" (? OutputResultOperations @@ YAXPBD0_NKN @ Z)
Yaniv

Ternyata ada bench.cpp yang hilang dari proyek tersebut. Tetapi bahkan setelah itu tidak dapat dikompilasi sampai saya menerapkan perbaikan ini ke fiptest.cpp github.com/weidai11/cryptopp/pull/151/files?diff=split Saya berharap mereka akan membuat pesanan dalam hal ini, seperti menambahkan file zip proyek menjadi git atau sesuatu. Dan ya, saya lalai mengatakan kompiler saya adalah VS2015 update 2. Intinya, ikuti petunjuk yang saya tulis dan berhasil.
Yaniv

@Yaniv - Untuk komentar pertama, apa yang Anda rekomendasikan agar pengguna lain tidak mengalami masalah? Untuk komentar kedua, kami berencana untuk mengambil tambalan setelah kami sepenuhnya diuji. Apakah ada yang bisa kami lakukan untuk sementara? (Saya menambahkan info tambahan ke jawaban ini, tetapi saya ingin memastikan pengguna tidak mengalami masalah).
jww

Pertama, terima kasih banyak telah melakukan ini. Crypto ++ benar-benar keren. Mengenai masalah build, coba pertahankan agar windows sln dan file project kompatibel dengan file terbaru dalam project, dan karena perubahan ini tentu saja, build windows ini harus ditautkan ke basis kode, dan bahkan mungkin berada di pohon sumber. Jika itu terlalu banyak, setidaknya pastikan file zip dengan lingkungan pembuatan studio visual kompatibel dengan rilis resmi stabil saat ini.
Yaniv

Mengenai tambalan untuk fiptest.cpp - tampaknya ada sesuatu yang berbeda tentang VS2015, jadi saya kira siapa pun yang ingin menggunakan VS2015 perlu menerapkan tambalan ini. Ini hanyalah kasus lain dalam blok #ifdef yang tampaknya menentukan callback debug yang tepat untuk VS2015, dan sangat mudah untuk menambal secara manual.
Yaniv

3

Saya mengalami masalah ini bersama dengan ketidakcocokan di ITERATOR_DEBUG_LEVEL. Karena masalah Minggu-malam tampaknya baik-baik saja dan baik untuk dilakukan, saya dikeluarkan untuk beberapa waktu. Bekerja di VS2017 IDE (Solution Explorer) Saya baru saja menambahkan / menyalin referensi file sumber ke proyek saya (ctrl-drag) dari proyek lain. Melihat properti-> C / C ++ / Preprocessor - di level file sumber, bukan level project - Saya melihat bahwa dalam konfigurasi Rilis _DEBUG yang ditentukan, bukan NDEBUG untuk file sumber ini. Yang mana saja perubahan yang diperlukan untuk menghilangkan masalah.


1

Masalah dapat diselesaikan dengan menambahkan CRT msvcrtd.lib di pustaka linker. Karena cryptlib.lib menggunakan versi debug CRT.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.