Seit VC 2005 wird die DLL-Version CRT ja grundsätzlich über ein Manifest geladen. Erzeuge ich Code, der die CRT verwendet, dann wird automatisch ein #pragma comment(linker,“/manifestdependency:..“) Eintrag erzeugt. Den entsprechenden Code dazu findet man in der _crtdefs.h Datei des entsprechenden Include-Pfades.
Dieser Manifest Eintrag wird später vom Manifest Tool (MT.EXE) gesammelt und im Manifest der Applikation oder der DLL verbaut.
Gesetzt den Fall ich habe Library erzeugt, die auch die DLL-Version der CRT verwendet, dann wird automatisch die entsprechende Version der CRT im Manifest hinterlegt. D.h. bei VS 2005 RTM die CRT Version 8.0.50727.42 und bei SP1 die CRT Version 8.0.50727.762
Wird nun für ein Projekt eine Library erzeugt mit einem VS 2005 RTM, und evtl. diese LIB lange nicht verändert und dann diese Library in einem Programm verwendet, dass mit VS 2005 SP1 erzeugt wird, dann werden beide CRT Versionen im Manifest eingetragen!
Der Lader ist zwar intelligent und lädt die letzte DLL (SP1). Aber undurchsichtig wird es in jedem Fall.
Vor allem wenn man wirklich mit evtl. einer älteren Version ausliefern möchte und SP1 auf der Ziel-Maschine nicht installiert ist.
Ich habe noch nicht genau herausbekommen wie entschieden wird welches der Manifesteintrag ist, der letzten Endes zählt. Scheinbar macht es auch nichts wenn, man die Version der CRT Versionen falsch angibt. Es wird dann die CRT mit der nächst höheren CRT geladen… (aber dazu muss ich noch etwas experimentieren)…
Dieses Verhalten ist gravierend unterschiedlich zu allen Vorgängerversionen von VC. Wie bisher hält Microsoft das Versprechen der binären Kompatibilität. Theoretisch müsste auch die mit RTM erzeugte LIB sofort funktionieren. Auch der Linker wird diese LIB sofort mit der entsprechenden MSVCR80(D).DLL verbinden. Nur hat er eben nicht das letzte Wort bei den Manifesten.
Man kann das ganze verhindern, indem man _CRT_NOFORCE_MANIFEST bevor die CRT Dateien inkludiert werden (am Besten in der stdafx.h oder in den Projekteinstellungen).
In diesem Fall wird kein #pragma, dass für den Manifest Eintrag verantwortlich ist, erzeugt.
Der Effekt ist dann wie gewollt, dass nur das eigentliche Projekt, dass dann das Executable erzeugt Einfluss auf die Ausgabe des Manifestes hat. Man kann also dann auch eine Lib-Datei mit VS-2005 SP1 erzeugen und mit einem VS-2005 RTM linken. Das Manifest wurde durch diese Lib dann nicht beeinflusst und so soll es IMHO sein.
Aber aufgepasst:
Seit VS-2005 muss in jedem Fall auf noch eine strenge Trennung der Release und Debug Versionen achten. Wenn nun kein Manifest mehr zum Beispiel in einer Release-Lib erzeugt wird, weil _CRT_NOFORCE_MANIFEST verwendet wird, nun aber diese Release Lib in ein Debug Projekt eingebunden wird. Dann wird das Executable implizit mit der MSVCR80.DLL gebunden, aber diese DLL kann nur über ein Manifest geladen werden. Das ist aber nicht vorhanden. Resultat ist das was in diesem Beitrag beschrieben steht: Manifest-Hölle „…MSVCR80.dll nicht gefunden…“ (siehe Nachtrag)
Ein Gedanke zu „Warum man seine Libraries mit _CRT_NOFORCE_MANIFEST erzeugen sollte“