Rozwiązanie LNK4098: defaultlib „MSVCRT” powoduje konflikt z

216

To ostrzeżenie:

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

jest dość powszechnym ostrzeżeniem w Visual Studio. Chciałbym zrozumieć dokładny powód i właściwy sposób (jeśli w ogóle), aby sobie z tym poradzić.

To pojawia się w kompilacji debugowania /MDd. Projekt jest powiązany z takimi rzeczami, jak okna Version.dlli pdh.dllktóre same się łączą MSVCRT.dll. Oczywiście nie mam ich wersji debugowania i nie mogę ich skompilować.

Więc dodałem /NODEFAULTLIB:MSVCRTdo linii poleceń linkera i faktycznie usunęło to ostrzeżenie. Ale co to właściwie robi? I dlaczego jest to konieczne?

buta
źródło

Odpowiedzi:

273

W vc \ lib są 4 wersje bibliotek linków CRT:

  • libcmt.lib: statyczna biblioteka linków CRT dla kompilacji wydania (/ MT)
  • libcmtd.lib: statyczna biblioteka linków CRT do kompilacji debugowania (/ MTd)
  • msvcrt.lib: importuj bibliotekę dla wersji DLL CRT (/ MD) wersji DLL
  • msvcrtd.lib: importuj bibliotekę dla debugowej wersji CRT DLL (/ MDd)

Spójrz na opcje linkera, Projekt + Właściwości, Linker, Wiersz poleceń. Zwróć uwagę, że te biblioteki nie są tutaj wymienione. Linker automatycznie rozpoznaje, który przełącznik / M został użyty przez kompilator, a który .lib powinien zostać połączony poprzez dyrektywę komentarza #pragma. Co ważne, dostaniesz straszne błędy łącza i trudne do zdiagnozowania błędy w czasie wykonywania, jeśli wystąpi rozbieżność między opcją / M a .lib, z którym łączysz się.

Zobaczysz komunikat o błędzie, który zacytowałeś, gdy linker otrzyma polecenie połączenia z msvcrt.lib i libcmt.lib. Co się stanie, jeśli połączysz kod skompilowany z / MT z kodem, który został połączony z / MD. Może istnieć tylko jedna wersja CRT.

/ NODEFAULTLIB mówi linkerowi, aby zignorował dyrektywę komentarza #pragma, która została wygenerowana z kodu skompilowanego / MT. Może to działać, chociaż mnóstwo innych błędów linkera nie jest rzadkością. Rzeczy takie jak errno , który jest zewnętrznym intem w statycznej wersji CRT, ale makropoleceniem funkcji w wersji DLL. Wielu innych to lubi.

Cóż, napraw ten problem we właściwy sposób, znajdź plik .obj lub .lib, który łączysz, który został skompilowany z niewłaściwą opcją / M. Jeśli nie masz pojęcia, możesz go znaleźć, przechodząc do plików .obj / .lib dla „/ MT”

Btw: pliki wykonywalne systemu Windows (takie jak version.dll) mają własną wersję CRT, aby wykonać zadanie. Znajduje się w folderze c: \ windows \ system32, nie można niezawodnie używać go do własnych programów, jego nagłówki CRT nie są nigdzie dostępne. Biblioteka CRT DLL używana przez program ma inną nazwę (np. Msvcrt90.dll).

Hans Passant
źródło
2
Dzięki temu postowi wciąż szukałem pliku .lib, który wciąż korzystał z / MDd i ostatecznie go znalazłem! Dzięki, +1
ceztko,
64
Trikiem, którego właśnie nauczyłem się, aby wyśledzić biblioteki, które pobierają niewłaściwe biblioteki CRT, jest dodanie /verbose:libdo dodatkowych opcji linkera. Pokazuje kolejność ładowania plików .lib, dzięki czemu możesz zobaczyć, gdzie został
pobrany
1
Hans, jakie to niebezpieczne? Jeśli nie możemy tego naprawić (otrzymujemy skompilowaną bibliotekę lib od naszego dostawcy), jakie konsekwencje mogą nas spotkać?
Ivan Nikitin,
3
Uważam, że komentarz @obmarg jest przydatny, ale nadal nie byłem pewien, jak używać pełnego wyjścia, dopóki nie znalazłem msdn.microsoft.com/en-us/library/aa267384(v=vs.60).aspx, który mówi, że pełne wyjście będzie informujemy tylko wszystkie biblioteki wykonawcze zaangażowane w problem z łączem. Nadal musisz ustalić, które dane wejściowe łącza zostały skompilowane z konfliktową biblioteką wykonawczą.
buzz3791
4
@ buzz3791 użyj / verbose zamiast / verbose: lib. Wyświetlane informacje obejmują proces przeszukiwania biblioteki i wyszczególniają każdą bibliotekę i nazwę obiektu (z pełną ścieżką), symbol usuwany z biblioteki oraz listę obiektów, które odwołują się do tego symbolu. / verbose może wyświetlić wszystkie informacje potrzebne do znalezienia złego faceta, który powoduje konflikty.
Yang Kui,
46

Oznacza to, że jedna z zależnych bibliotek DLL jest skompilowana z inną biblioteką wykonawczą .

Projekt -> Właściwości -> C / C ++ -> Generowanie kodu -> Biblioteka wykonawcza

Przejrzyj wszystkie biblioteki i sprawdź, czy są one skompilowane w ten sam sposób.

Więcej informacji o tym błędzie w tym linku:

ostrzeżenie LNK4098: defaultlib „LIBCD” powoduje konflikty z użyciem innych bibliotek

Yochai Timmer
źródło
To był powód błędu! Dzięki za wskazówkę.
rkachach
1
To najlepsza odpowiedź dla mniej doświadczonych programistów.
meolic
32

IMO ten link od Yochai Timmer był bardzo dobry i odpowiedni, ale bolesny do przeczytania. Napisałem streszczenie.

Yochai, jeśli to przeczytasz, zobacz notatkę na końcu.


W pierwotnym poście przeczytano: ostrzeżenie LNK4098: defaultlib „LIBCD” powoduje konflikt z użyciem innych bibliotek

Błąd

LINK: ostrzeżenie LNK4098: defaultlib „LIBCD” powoduje konflikty z użyciem innych bibliotek; użyj / NODEFAULTLIB: biblioteka

Znaczenie

jedna część systemu została skompilowana do korzystania z biblioteki jednowątkowej standardowej (libc) z informacjami debugowania (libcd), która jest statycznie połączona

podczas gdy inna część systemu została skompilowana do korzystania z wielowątkowej standardowej biblioteki bez informacji debugowania, która znajduje się w bibliotece DLL i korzysta z dynamicznego łączenia

Jak rozwiązać

  • Zignoruj ​​to ostrzeżenie, w końcu to tylko ostrzeżenie. Jednak Twój program zawiera teraz wiele wystąpień tych samych funkcji.

  • Użyj opcji linkera / NODEFAULTLIB: lib. To nie jest kompletne rozwiązanie, nawet jeśli możesz połączyć swój program w ten sposób, ignorujesz znak ostrzegawczy: kod został skompilowany dla różnych środowisk, część kodu może być skompilowana dla modelu z jednym wątkiem, podczas gdy inny kod jest wielowątkowy.

  • [...] przeszukuj wszystkie biblioteki i upewnij się, że mają prawidłowe ustawienia linków

W tym ostatnim, jak wspomniano w oryginalnym poście, mogą pojawić się dwa typowe problemy:

  • Masz bibliotekę strony trzeciej, która jest inaczej połączona z twoją aplikacją.

  • Masz inne dyrektywy osadzone w kodzie: zwykle jest to MFC. Jeśli jakieś moduły w twoim systemie łączą się z MFC, wszystkie twoje moduły muszą nominalnie połączyć się z tą samą wersją MFC.

W takich przypadkach upewnij się, że rozumiesz problem i wybierasz rozwiązania.


Uwaga: Chciałem dołączyć to podsumowanie linku Yochai Timmer do własnej odpowiedzi, ale ponieważ niektórzy ludzie mają problem z poprawnym sprawdzeniem poprawek, musiałem napisać je w osobnej odpowiedzi. Przepraszam

ForceMagic
źródło
7

Otrzymuję to za każdym razem, gdy chcę utworzyć aplikację w VC ++.

Kliknij projekt prawym przyciskiem myszy, wybierz Właściwości, a następnie w obszarze „Właściwości konfiguracji | C / C ++ | Generowanie kodu ”, wybierz„ Debugowanie wielowątkowe (/ MTd) ”w celu konfiguracji debugowania.

Pamiętaj, że nie zmienia to ustawień konfiguracji wydania - musisz przejść do tej samej lokalizacji i wybrać opcję „Wielowątkowe (/ MT)” dla wydania.

użytkownik1016736
źródło
4

Kliknij projekt prawym przyciskiem myszy, wybierz Właściwości, a następnie w obszarze „Właściwości konfiguracji | Łącznik | Wejście | Zignoruj ​​konkretną bibliotekę i napisz msvcrtd.lib

raehee
źródło