Menyelesaikan LNK4098: defaultlib 'MSVCRT' konflik dengan

227

Peringatan ini:

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

adalah peringatan yang cukup umum di Visual Studio. Saya ingin memahami alasan pasti untuk itu dan cara yang benar (jika ada) untuk menanganinya.

Ini muncul dalam build debug, yang dikompilasi dengan /MDd. Proyek ini ditautkan ke hal-hal seperti jendela Version.dlldan pdh.dllyang ditautkan dengan sendirinya MSVCRT.dll. Jelas, saya tidak memiliki versi debug ini dan tidak dapat mengkompilasinya.

Jadi saya menambahkan /NODEFAULTLIB:MSVCRTke baris perintah linker dan itu benar-benar menghapus peringatan. Tapi apa yang sebenarnya dilakukan ini? Dan mengapa itu perlu?

shoosh
sumber

Jawaban:

279

Ada 4 versi pustaka tautan CRT yang ada di vc \ lib:

  • libcmt.lib: pustaka tautan CRT statis untuk build rilis (/ MT)
  • libcmtd.lib: pustaka tautan CRT statis untuk build debug (/ MTd)
  • msvcrt.lib: pustaka impor untuk rilis versi DLL CRT (/ MD)
  • msvcrtd.lib: pustaka impor untuk versi debug DLL CRT (/ MDd)

Lihat opsi linker, Project + Properties, Linker, Command Line. Perhatikan bagaimana pustaka ini tidak disebutkan di sini. Linker secara otomatis mencari tahu saklar / M apa yang digunakan oleh kompilator dan .lib mana yang harus ditautkan melalui perintah komentar #pragma. Agak penting, Anda akan mendapatkan kesalahan tautan yang mengerikan dan kesalahan runtime sulit didiagnosis jika ada ketidakcocokan antara opsi / M dan .lib yang Anda tautkan.

Anda akan melihat pesan kesalahan yang Anda kutip saat penaut diberi tahu untuk menautkan ke msvcrt.lib dan libcmt.lib. Yang akan terjadi jika Anda menautkan kode yang dikompilasi dengan / MT dengan kode yang ditautkan dengan / MD. Hanya ada satu versi CRT.

/ NODEFAULTLIB memberi tahu linker untuk mengabaikan perintah komentar #pragma yang dihasilkan dari kode yang dikompilasi / MT. Ini mungkin berhasil, meskipun banyak kesalahan linker lain yang tidak biasa. Hal-hal seperti errno , yang merupakan int eksternal dalam versi CRT statis tetapi di-makro ke fungsi dalam versi DLL. Banyak yang lain seperti itu.

Nah, perbaiki masalah ini dengan Cara Yang Benar, cari file .obj atau .lib yang Anda tautkan yang dikompilasi dengan opsi / M yang salah. Jika Anda tidak memiliki petunjuk, Anda dapat menemukannya dengan grep file .obj / .lib untuk "/ MT"

Btw: Windows executable (seperti version.dll) memiliki versi CRT mereka sendiri untuk menyelesaikan pekerjaan mereka. Itu terletak di c: \ windows \ system32, Anda tidak dapat menggunakannya dengan andal untuk program Anda sendiri, header CRT-nya tidak tersedia di mana pun. CRT DLL yang digunakan oleh program Anda memiliki nama yang berbeda (seperti msvcrt90.dll).

Hans Passant
sumber
2
Berkat posting ini, saya terus mencari .lib yang masih menggunakan / MDd dan akhirnya saya menemukannya! Terima kasih, +1
ceztko
66
Trik yang baru saya pelajari untuk melacak perpustakaan yang menarik perpustakaan CRT yang salah adalah dengan menambahkan /verbose:libopsi penaut tambahan. Ini menunjukkan urutan file .lib dimuat, memungkinkan Anda untuk melihat di mana yang salah ditarik masuk.
obmarg
1
Hans, betapa berbahayanya itu? Jika kami tidak dapat memperbaikinya (kami mendapatkan lib terkompilasi dari vendor kami), konsekuensi apa yang mungkin kami hadapi?
Ivan Nikitin
3
Saya menemukan komentar @obmarg 'berguna tetapi masih tidak yakin bagaimana menggunakan output verbose sampai saya menemukan msdn.microsoft.com/en-us/library/aa267384(v=vs.60).aspx yang mengatakan output verbose akan hanya memberi tahu Anda semua pustaka runtime yang terlibat dalam masalah tautan. Anda masih harus mencari tahu input tautan mana yang telah dikompilasi dengan Perpustakaan Runtime yang bertentangan.
buzz3791
4
@ buzz3791 gunakan / verbose alih-alih / verbose: lib. Informasi yang ditampilkan mencakup proses pencarian pustaka dan daftar setiap pustaka dan nama objek (dengan jalur lengkap), simbol yang diselesaikan dari pustaka, dan daftar objek yang mereferensikan simbol. / verbose dapat menampilkan semua info yang Anda butuhkan untuk menemukan orang jahat yang menyebabkan konflik.
Yang Kui
49

Ini berarti bahwa salah satu dll dependen dikompilasi dengan pustaka run-time yang berbeda .

Proyek -> Properti -> C / C ++ -> Pembuatan Kode -> Perpustakaan Runtime

Pergi ke semua perpustakaan dan lihat bahwa mereka dikompilasi dengan cara yang sama.

Lebih lanjut tentang kesalahan ini di tautan ini:

peringatan LNK4098: defaultlib "LIBCD" konflik dengan penggunaan libs lain

Yochai Timmer
sumber
Itulah alasan kesalahannya! Terima kasih atas tipnya.
rkachach
1
Ini adalah jawaban terbaik untuk programmer yang kurang berpengalaman.
meolic
32

Tautan IMO dari Yochai Timmer ini sangat bagus dan relevan tetapi menyakitkan untuk dibaca. Saya menulis ringkasan.

Yochai, jika Anda pernah membaca ini, silakan lihat catatan di bagian akhir.


Untuk postingan asli baca: peringatan LNK4098: defaultlib "LIBCD" bentrok dengan penggunaan libs lain

Kesalahan

LINK: peringatan LNK4098: defaultlib "LIBCD" bertentangan dengan penggunaan libs lain; gunakan / NODEFAULTLIB: perpustakaan

Berarti

satu bagian dari sistem dikompilasi untuk menggunakan pustaka standar berulir tunggal (libc) dengan informasi debug (libcd) yang ditautkan secara statis

sementara bagian lain dari sistem dikompilasi untuk menggunakan pustaka standar multi-utas tanpa informasi debug yang berada di DLL dan menggunakan tautan dinamis

Bagaimana mengatasinya

  • Abaikan peringatannya, lagipula itu hanya peringatan. Namun, program Anda sekarang berisi banyak contoh dari fungsi yang sama.

  • Gunakan opsi linker / NODEFAULTLIB: lib. Ini bukan solusi lengkap, bahkan jika Anda bisa membuat program Anda ditautkan dengan cara ini Anda mengabaikan tanda peringatan: kode telah dikompilasi untuk lingkungan yang berbeda, beberapa kode Anda mungkin dikompilasi untuk model ulir tunggal sementara kode lainnya dikompilasi multi-utas.

  • [...] menelusuri semua perpustakaan Anda dan memastikan mereka memiliki pengaturan tautan yang benar

Yang terakhir, seperti yang disebutkan di posting asli, dua masalah umum dapat muncul:

  • Anda memiliki perpustakaan pihak ketiga yang ditautkan secara berbeda ke aplikasi Anda.

  • Anda memiliki arahan lain yang disematkan dalam kode Anda: biasanya ini adalah MFC. Jika ada modul dalam sistem Anda yang ditautkan dengan MFC, semua modul Anda harus ditautkan secara nominal dengan versi MFC yang sama.

Untuk kasus tersebut, pastikan Anda memahami masalahnya dan memutuskan di antara solusinya.


Catatan: Saya ingin memasukkan ringkasan tautan Yochai Timmer ke dalam jawabannya sendiri, tetapi karena beberapa orang mengalami kesulitan untuk meninjau hasil edit dengan benar, saya harus menulisnya di jawaban terpisah. Maaf

ForceMagic
sumber
7

Saya mendapatkan ini setiap kali saya ingin membuat aplikasi di VC ++.

Klik kanan proyek, pilih Properties lalu di bawah 'Configuration properties | C / C ++ | Code Generation ', pilih "Multi-threaded Debug (/ MTd)" untuk konfigurasi Debug.

Perhatikan bahwa ini tidak mengubah pengaturan untuk konfigurasi Rilis Anda - Anda harus pergi ke lokasi yang sama dan memilih "Multi-threaded (/ MT)" untuk Rilis.

pengguna1016736
sumber
5

Klik kanan proyek, pilih Properties lalu di bawah 'Configuration properties | Linker | Masukan | Abaikan Library tertentu dan tulis msvcrtd.lib

raehee
sumber