LNK4098 lösen: Standardlib 'MSVCRT' steht in Konflikt mit

216

Diese Warnung:

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

ist eine ziemlich häufige Warnung in Visual Studio. Ich würde gerne den genauen Grund dafür verstehen und den richtigen Weg (wenn überhaupt), damit umzugehen.

Dies geschieht in einem Debug-Build, der mit kompiliert wurde /MDd. Das Projekt wird auf Dinge wie Fenster verknüpft Version.dllund pdh.dlldie sich mit verknüpfen MSVCRT.dll. Offensichtlich habe ich keine Debug-Versionen davon und kann sie nicht kompilieren.

Also habe ich /NODEFAULTLIB:MSVCRTder Linker-Befehlszeile hinzugefügt und die Warnung wurde tatsächlich entfernt. Aber was macht das eigentlich? Und warum ist es notwendig?

shoosh
quelle

Antworten:

273

In vc \ lib sind 4 Versionen der CRT-Linkbibliotheken vorhanden:

  • libcmt.lib: statische CRT-Linkbibliothek für einen Release Build (/ MT)
  • libcmtd.lib: statische CRT-Linkbibliothek für einen Debugbuild (/ MTd)
  • msvcrt.lib: Importbibliothek für die Release-DLL-Version der CRT (/ MD)
  • msvcrtd.lib: Importbibliothek für die Debug-DLL-Version der CRT (/ MDd)

Schauen Sie sich die Linker-Optionen, Projekt + Eigenschaften, Linker, Befehlszeile an. Beachten Sie, dass diese Bibliotheken hier nicht erwähnt werden. Der Linker ermittelt automatisch, welcher / M-Schalter vom Compiler verwendet wurde und welche .lib über eine # Pragma-Kommentaranweisung verknüpft werden soll. Ein bisschen wichtig, Sie würden schreckliche Linkfehler bekommen und Laufzeitfehler schwer zu diagnostizieren, wenn es eine Nichtübereinstimmung zwischen der / M-Option und der .lib gibt, mit der Sie verknüpfen.

Die von Ihnen angegebene Fehlermeldung wird angezeigt, wenn der Linker angewiesen wird, auf msvcrt.lib und libcmt.lib zu verlinken. Was passiert, wenn Sie Code, der mit / MT kompiliert wurde, mit Code verknüpfen, der mit / MD verknüpft wurde. Es kann nur eine Version der CRT geben.

/ NODEFAULTLIB weist den Linker an, die # Pragma-Kommentaranweisung zu ignorieren, die aus dem / MT-kompilierten Code generiert wurde. Dies könnte funktionieren, obwohl eine Reihe anderer Linkerfehler nicht ungewöhnlich sind. Dinge wie errno , ein externes int in der statischen CRT-Version, das jedoch zu einer Funktion in der DLL-Version makro- bearbeitet wurde. Viele andere mögen das.

Beheben Sie dieses Problem auf die richtige Weise und suchen Sie die .obj- oder .lib-Datei, die Sie verknüpfen und die mit der falschen / M-Option kompiliert wurde. Wenn Sie keine Ahnung haben, können Sie sie finden, indem Sie die .obj / .lib-Dateien nach "/ MT" durchsuchen.

Übrigens: Die ausführbaren Windows-Dateien (wie version.dll) haben eine eigene CRT-Version, um ihre Arbeit zu erledigen. Es befindet sich in c: \ windows \ system32. Sie können es nicht zuverlässig für Ihre eigenen Programme verwenden. Die CRT-Header sind nirgendwo verfügbar. Die von Ihrem Programm verwendete CRT-DLL hat einen anderen Namen (wie msvcrt90.dll).

Hans Passant
quelle
2
Dank dieses Beitrags suchte ich weiter nach einer .lib, die noch / MDd verwendete, und fand schließlich eine! Vielen Dank, +1
Ceztko
64
Ein Trick, den ich gerade gelernt habe, um Bibliotheken aufzuspüren, die die falschen CRT-Bibliotheken abrufen, besteht darin /verbose:lib, die zusätzlichen Linker-Optionen zu ergänzen . Es zeigt die Reihenfolge, in der .lib-Dateien geladen werden, so dass Sie sehen können, wo die falsche eingezogen wurde.
Obmarg
1
Hans, wie gefährlich ist es? Welche Konsequenzen können wir haben, wenn wir das Problem nicht beheben können (wir erhalten eine kompilierte Bibliothek von unserem Anbieter)?
Ivan Nikitin
3
Ich fand den Kommentar von @obmarg nützlich, war mir aber immer noch nicht sicher, wie ich die ausführliche Ausgabe verwenden sollte, bis ich msdn.microsoft.com/en-us/library/aa267384(v=vs.60).aspx fand, das besagt, dass die ausführliche Ausgabe dies tun wird Teilen Sie Ihnen nur alle Laufzeitbibliotheken mit, die am Linkproblem beteiligt sind. Sie müssen dann noch herausfinden, welche Verknüpfungseingabe mit der in Konflikt stehenden Laufzeitbibliothek kompiliert wurde.
Buzz3791
4
@uzz3791 benutze / verbose anstelle von / verbose: lib. Die angezeigten Informationen umfassen den Bibliothekssuchprozess und listen alle Bibliotheks- und Objektnamen (mit vollständigem Pfad), das aus der Bibliothek aufgelöste Symbol und eine Liste von Objekten auf, die auf das Symbol verweisen. / verbose kann alle Informationen anzeigen, die Sie benötigen, um den Bösewicht zu finden, der die Konflikte verursacht.
Yang Kui
46

Dies bedeutet, dass eine der abhängigen DLLs mit einer anderen Laufzeitbibliothek kompiliert wird .

Projekt -> Eigenschaften -> C / C ++ -> Codegenerierung -> Laufzeitbibliothek

Sehen Sie sich alle Bibliotheken an und stellen Sie sicher, dass sie auf dieselbe Weise kompiliert werden.

Mehr zu diesem Fehler in diesem Link:

Warnung LNK4098: Die Standardlib "LIBCD" steht in Konflikt mit der Verwendung anderer Bibliotheken

Yochai Timmer
quelle
Das war der Grund für den Fehler! Danke für den Tipp.
Rkachach
1
Dies ist die beste Antwort für weniger erfahrene Programmierer.
Meolic
32

IMO war dieser Link von Yochai Timmer sehr gut und relevant, aber schmerzhaft zu lesen. Ich habe eine Zusammenfassung geschrieben.

Yochai, wenn Sie dies jemals gelesen haben, lesen Sie bitte den Hinweis am Ende.


Für den ursprünglichen Beitrag lesen Sie: Warnung LNK4098: Die Standardlib "LIBCD" steht in Konflikt mit der Verwendung anderer Bibliotheken

Error

LINK: Warnung LNK4098: Die Standardlib "LIBCD" steht in Konflikt mit der Verwendung anderer Bibliotheken. benutze / NODEFAULTLIB: Bibliothek

Bedeutung

Ein Teil des Systems wurde kompiliert, um eine Single-Threaded-Standardbibliothek (libc) mit Debug-Informationen (libcd) zu verwenden, die statisch verknüpft sind

Ein anderer Teil des Systems wurde kompiliert, um eine Multibread-Standardbibliothek ohne Debug-Informationen zu verwenden, die sich in einer DLL befindet und dynamische Verknüpfungen verwendet

Wie zu lösen

  • Ignorieren Sie die Warnung, schließlich handelt es sich nur um eine Warnung. Ihr Programm enthält jetzt jedoch mehrere Instanzen derselben Funktionen.

  • Verwenden Sie die Linker-Option / NODEFAULTLIB: lib. Dies ist keine vollständige Lösung, auch wenn Sie Ihr Programm so verknüpfen können, dass Sie ein Warnzeichen ignorieren: Der Code wurde für verschiedene Umgebungen kompiliert, ein Teil Ihres Codes wurde möglicherweise für ein einzelnes Thread-Modell kompiliert, während anderer Code dies ist Multithreading.

  • [...] durchsuchen Sie alle Ihre Bibliotheken und stellen Sie sicher, dass sie über die richtigen Linkeinstellungen verfügen

In letzterem können, wie im ursprünglichen Beitrag erwähnt, zwei häufige Probleme auftreten:

  • Sie haben eine Drittanbieter-Bibliothek, die anders mit Ihrer Anwendung verknüpft ist.

  • Sie haben andere Anweisungen in Ihren Code eingebettet: Normalerweise ist dies der MFC. Wenn Module in Ihrem System mit MFC verknüpft sind, müssen alle Ihre Module nominell mit derselben Version von MFC verknüpft sein.

Stellen Sie in diesen Fällen sicher, dass Sie das Problem verstehen und entscheiden Sie sich für eine der Lösungen.


Hinweis: Ich wollte diese Zusammenfassung von Yochai Timmers Link in seine eigene Antwort aufnehmen, aber da einige Leute Probleme haben, Änderungen richtig zu überprüfen, musste ich sie in eine separate Antwort schreiben. Es tut uns leid

ForceMagic
quelle
7

Ich bekomme dies jedes Mal, wenn ich eine Anwendung in VC ++ erstellen möchte.

Klicken Sie mit der rechten Maustaste auf das Projekt, wählen Sie Eigenschaften und dann unter 'Konfigurationseigenschaften | C / C ++ | Codegenerierung ', wählen Sie "Multithread-Debug (/ MTd)" für die Debug-Konfiguration.

Beachten Sie, dass dies die Einstellung für Ihre Release-Konfiguration nicht ändert. Sie müssen an denselben Speicherort gehen und "Multi-Threaded (/ MT)" für Release auswählen.

user1016736
quelle
4

Klicken Sie mit der rechten Maustaste auf das Projekt, wählen Sie Eigenschaften und dann unter 'Konfigurationseigenschaften | Linker | Eingabe | Ignorieren Sie eine bestimmte Bibliothek und schreiben Sie msvcrtd.lib

raehee
quelle