Розв’язання LNK4098: по умолчанні 'MSVCRT' конфліктує з


216

Це попередження:

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

є досить поширеним попередженням у Visual Studio. Я хотів би зрозуміти точну причину цього і правильний спосіб (якщо він взагалі є).

Це з'являється у налагодженні, складеному з /MDd. Проект пов'язаний з такими речами, як Windows, Version.dllі з pdh.dllякими вони пов'язані MSVCRT.dll. Очевидно, що я не маю версій налагодження цих версій і не можу їх компілювати.

Тож я додав /NODEFAULTLIB:MSVCRTдо командного рядка linker, і він фактично видалив попередження. Але що це насправді робить? І навіщо це потрібно?

Відповіді:


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, Command Line. Зверніть увагу, як ці бібліотеки тут не згадуються. Лінкер автоматично визначає, який / M комутатор використовувався компілятором, а який .lib повинен бути пов'язаний через директиву про коментарі #pragma. Як би важливо, ви отримаєте жахливі помилки посилань і важко діагностувати помилки виконання, якщо не було б збіг між параметром / M та .lib, з яким ви посилаєтесь.

Ви побачите повідомлення про помилку, яке ви цитували, коли лінкеру буде сказано як посилання на msvcrt.lib та libcmt.lib. Що станеться, якщо ви зв’яжете код, який був складений з / MT, з кодом, який був пов'язаний з / MD. Існує лише одна версія CRT.

/ NODEFAULTLIB повідомляє лінкеру ігнорувати директиву коментарів #pragma, яка була сформована з компільованого коду / MT. Це може спрацювати, хоча низка інших помилок лінкера не рідкість. Такі речі, як errno , що є зовнішнім int у статичній CRT-версії, але макроед до функції у версії DLL. Багато інших подібне.

Ну, виправте цю проблему правильним шляхом, знайдіть файл .obj або .lib, який ви посилаєте, який був складений з неправильною опцією / M. Якщо у вас немає поняття, ви можете знайти його, перетягнувши файли .obj / .lib для "/ MT".

Btw: у виконуваних файлів Windows (наприклад, version.dll) є своя версія CRT, щоб виконати свою роботу. Він розташований у c: \ windows \ system32, ви не можете надійно використовувати його для власних програм, його CRT-заголовки недоступні ніде. CRL DLL, який використовується вашою програмою, має іншу назву (наприклад, 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: за замовчуванням "LIBCD" конфліктує з використанням інших ліб


Це була причина помилки! Дякую за пораду.
ркачач

1
Це найкраща відповідь для менш досвідчених програмістів.
меолічний

32

IMO це посилання від Yochai Timmer було дуже хорошим і релевантним, але болісно читати. Я написав резюме.

Йохай, якщо ти коли-небудь це читав, будь ласка, дивись замітку в кінці.


У початковому дописі прочитано: попередження LNK4098: за замовчуванням "LIBCD" конфліктує з використанням інших ліб

Помилка

ЛІНКА: попередження LNK4098: за замовчуванням "LIBCD" конфліктує з використанням інших ліб; використання / NODEFAULTLIB: бібліотека

Значення

одна частина системи була складена для використання єдиної стандартної бібліотеки (libc) з інформацією про налагодження (libcd), яка статично пов'язана

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

Як вирішити

  • Ігноруйте попередження, адже це лише попередження. Однак зараз у вашій програмі є кілька примірників одних і тих же функцій.

  • Скористайтеся опцією лінкера / NODEFAULTLIB: lib. Це не повне рішення, навіть якщо ви можете змусити вашу програму зв’язуватися таким чином, ви ігноруєте попереджувальний знак: код був складений для різних середовищ, частина вашого коду може бути складена для однієї потокової моделі, тоді як інший код багатопотокові.

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

В останньому, як це було сказано в оригіналі публікації, можуть виникнути дві поширені проблеми:

  • У вас є стороння бібліотека, яка по-різному пов'язана з вашою заявою.

  • У ваш код вбудовані інші директиви: зазвичай це MFC. Якщо будь-які модулі у вашій системі посилаються на MFC, всі ваші модулі повинні номінально посилатися на одну і ту ж версію MFC.

У цих випадках переконайтеся, що ви розумієте проблему та вирішуєте рішення.


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


7

Я отримую це щоразу, коли хочу створити додаток у VC ++.

Клацніть правою кнопкою миші проект, виберіть "Властивості" та виберіть "Властивості конфігурації |" C / C ++ | Генерація коду ", виберіть" Багатопотокова налагодження (/ MTd) "для налаштування налагодження.

Зауважте, що це не змінює налаштування для вашої конфігурації випуску - вам потрібно буде перейти в те саме місце та вибрати "Багатопотоковий (/ MT)" для випуску.


4

Клацніть правою кнопкою миші проект, виберіть "Властивості" та виберіть "Властивості конфігурації |" Лінкер | Введення | Ігноруйте конкретну бібліотеку і запишіть msvcrtd.lib

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.