Разрешение LNK4098: конфликт библиотеки по умолчанию «MSVCRT» конфликтует с

217

Это предупреждение:

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

это довольно распространенное предупреждение в Visual Studio. Я хотел бы понять точную причину этого и правильный способ (если вообще) справиться с этим.

Это происходит в отладочной сборке, скомпилированной с /MDd. Проект связан с такими вещами, как окна Version.dllи с pdh.dllкоторыми они связаны MSVCRT.dll. Очевидно, у меня нет этих отладочных версий, и я не могу их скомпилировать.

Поэтому я добавил /NODEFAULTLIB:MSVCRTв командную строку компоновщика, и он действительно удалил предупреждение. Но что это на самом деле делает? И зачем это нужно?

shoosh
источник

Ответы:

273

В vc \ lib есть 4 версии библиотек ссылок CRT:

  • libcmt.lib: статическая библиотека ссылок CRT для сборки выпуска (/ MT)
  • libcmtd.lib: статическая библиотека ссылок CRT для отладочной сборки (/ MTd)
  • msvcrt.lib: библиотека импорта для версии DLL CRT (/ MD)
  • msvcrtd.lib: библиотека импорта для отладочной DLL-версии CRT (/ MDd)

Посмотрите на параметры компоновщика, Project + Properties, Linker, Командная строка. Обратите внимание, что эти библиотеки не упоминаются здесь. Компоновщик автоматически определяет, какой ключ / M использовался компилятором и какой .lib должен быть связан с помощью директивы комментария #pragma. Очень важно, что вы получите ужасные ошибки ссылок и трудно диагностировать ошибки времени выполнения, если будет несоответствие между параметром / M и .lib, с которым вы ссылаетесь.

Вы увидите сообщение об ошибке, которое вы процитировали, когда компоновщик получит указание на ссылку на msvcrt.lib и libcmt.lib. Что произойдет, если вы свяжете код, который был скомпилирован с / MT с кодом, который был связан с / MD. Может быть только одна версия ЭЛТ.

/ NODEFAULTLIB говорит компоновщику игнорировать директиву комментария #pragma, сгенерированную из скомпилированного кода / MT. Это может сработать, хотя множество других ошибок компоновщика не редкость. Такие вещи, как errno , который является extern int в статической версии CRT, но макропрограммирован для функции в версии DLL. Многим другим это нравится.

Что ж, исправьте эту проблему Правильным путем, найдите файл .obj или .lib, на который вы ссылаетесь, который был скомпилирован с неправильной опцией / M. Если у вас нет подсказки, вы можете найти ее, выбрав .obj / .lib файлы для "/ MT"

Кстати: исполняемые файлы Windows (например, version.dll) имеют свою собственную версию CRT, чтобы выполнить свою работу. Он находится в каталоге c: \ windows \ system32, вы не можете надежно использовать его для своих собственных программ, его заголовки CRT нигде не доступны. DLL-библиотека CRT, используемая вашей программой, имеет другое имя (например, msvcrt90.dll).

Ганс Пассант
источник
2
Благодаря этому сообщению я продолжал искать .lib, который все еще использовал / MDd, и в конце концов нашел его! Спасибо, +1
ceztko
64
Уловка, которую я только что узнал, чтобы отследить библиотеки, которые извлекают неправильные библиотеки CRT, заключается в добавлении /verbose:libк дополнительным опциям компоновщика. Он показывает порядок загрузки файлов
.lib
1
Ганс, насколько это опасно? Если мы не можем это исправить (мы получаем скомпилированную библиотеку от нашего поставщика), с какими последствиями мы можем столкнуться?
Иван Никитин
3
Я нашел комментарий @obmarg полезным, но все еще не знал, как использовать подробный вывод, пока не нашел msdn.microsoft.com/en-us/library/aa267384(v=vs.60).aspx, в котором говорится, что подробный вывод будет только рассказать вам все библиотеки времени выполнения, участвующие в проблеме со связью. Вы все еще должны выяснить, какая ссылка была скомпилирована с конфликтующей библиотекой времени выполнения.
buzz3791
4
@ buzz3791 используйте / verbose вместо / verbose: lib. Отображаемая информация включает в себя процесс поиска в библиотеке и перечисляет каждую библиотеку и имя объекта (с полным путем), символ, определяемый из библиотеки, и список объектов, которые ссылаются на символ. / verbose может отображать всю информацию, необходимую вам, чтобы найти плохого парня, который вызывает конфликты.
Ян Куи
46

Это означает, что один из зависимых dll скомпилирован с другой библиотекой времени выполнения .

Проект -> Свойства -> C / C ++ -> Генерация кода -> Библиотека времени выполнения

Просмотрите все библиотеки и убедитесь, что они скомпилированы одинаково.

Подробнее об этой ошибке в этой ссылке:

предупреждение LNK4098: defaultlib "LIBCD" конфликтует с использованием других библиотек

Йохай Тиммер
источник
Это было причиной ошибки! Спасибо за чаевые.
ркачач
1
Это лучший ответ для менее опытных программистов.
Меолик
32

ИМО, эта ссылка от Йохая Тиммера была очень хорошей и актуальной, но больно читать. Я написал резюме.

Йохай, если ты когда-нибудь прочитаешь это, пожалуйста, посмотри записку в конце.


Для оригинального сообщения читать: предупреждение LNK4098: defaultlib "LIBCD" конфликтует с использованием других библиотек

ошибка

ССЫЛКА: предупреждение LNK4098: defaultlib "LIBCD" конфликтует с использованием других библиотек; использовать / NODEFAULTLIB: библиотека

Смысл

одна часть системы была скомпилирована для использования однопоточной стандартной (libc) библиотеки с отладочной информацией (libcd), которая статически связана

в то время как другая часть системы была скомпилирована для использования многопоточной стандартной библиотеки без отладочной информации, которая находится в DLL и использует динамическое связывание

Как решить

  • Не обращайте внимания на предупреждение, ведь это всего лишь предупреждение. Однако ваша программа теперь содержит несколько экземпляров одних и тех же функций.

  • Используйте параметр компоновщика / NODEFAULTLIB: lib. Это не полное решение, даже если вы можете заставить свою программу связываться таким образом, вы игнорируете предупреждающий знак: код был скомпилирован для разных сред, часть вашего кода может быть скомпилирована для однопоточной модели, в то время как другой код многопоточный.

  • [...] просмотрите все ваши библиотеки и убедитесь, что они имеют правильные настройки ссылок

В последнем, как это упоминалось в оригинальном сообщении, могут возникнуть две общие проблемы:

  • У вас есть сторонняя библиотека, которая по-разному связана с вашим приложением.

  • У вас есть другие директивы, встроенные в ваш код: обычно это MFC. Если какие-либо модули в вашей системе связаны с MFC, все ваши модули должны быть номинально связаны с одной и той же версией MFC.

В этих случаях убедитесь, что вы понимаете проблему и выбираете решение.


Примечание. Я хотел включить это краткое изложение ссылки Йохая Тиммера в его собственный ответ, но, поскольку у некоторых людей возникают проблемы с корректным рассмотрением изменений, мне пришлось написать это в отдельном ответе. сожалею

ForceMagic
источник
7

Я получаю это каждый раз, когда хочу создать приложение на VC ++.

Щелкните правой кнопкой мыши проект, выберите «Свойства», затем в разделе «Свойства конфигурации | C / C ++ | Генерация кода », выберите« Многопоточная отладка (/ MTd) »для конфигурации отладки.

Обратите внимание, что это не меняет настройки для вашей версии выпуска - вам нужно перейти в то же место и выбрать «Многопоточность (/ MT)» для выпуска.

user1016736
источник
4

Щелкните правой кнопкой мыши проект, выберите «Свойства», затем в разделе «Свойства конфигурации | Линкер | Вход | Игнорировать конкретную библиотеку и написать msvcrtd.lib

raehee
источник