Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel wird beschrieben, wie Sie die C-Laufzeit verwenden.
Originalproduktversion: Visual C++
Ursprüngliche KB-Nummer: 94248
Abschnitt 1: Drei Formen von C-Laufzeitbibliotheken (CRT) sind verfügbar.
Es gibt drei Formen der C-Laufzeitbibliothek, die mit dem Win32 SDK bereitgestellt wird:
LIBC. LIB ist eine statisch verknüpfte Bibliothek für Singlethread-Programme.
LIBCMT. LIB ist eine statisch verknüpfte Bibliothek, die Multithread-Programme unterstützt.
CRTDLL. LIB ist eine Importbibliothek für CRTDLL.DLL, die auch Multithreadprogramme unterstützt. CRTDLL.DLL selbst ist Teil von Windows NT.
Microsoft Visual C++ 32-Bit-Edition enthält diese drei Formen, aber der CRT in einer DLL heißt MSVCRT. BEFREIEN. Die DLL ist verteilbar. Der Name hängt von der Version von VC++ ab (d. a. MSVCRT10.DLL oder MSVCRT20.DLL). Beachten Sie jedoch, dass MSVCRT10.DLL für Win32s nicht unterstützt wird, während CRTDLL. LIB wird für Win32s unterstützt. MSVCRT20.DLL kommt in zwei Versionen: eines für Windows NT und das andere für Win32s.
Abschnitt 2: Verwenden der CRT-Bibliotheken beim Erstellen einer DLL
Beim Erstellen einer DLL, die eine der C-Laufzeitbibliotheken verwendet, um sicherzustellen, dass das CRT ordnungsgemäß initialisiert ist, entweder
Die Initialisierungsfunktion muss benannt
DllMain()
werden, und der Einstiegspunkt muss mit der Linkeroption angegeben werden.-entry:_DllMainCRTStartup@12
oder
Der Einstiegspunkt der DLL muss explizit auf Prozessanfügung und Prozessablösung aufrufen
CRT_INIT()
.
Dadurch können die C-Laufzeitbibliotheken C-Laufzeitdaten ordnungsgemäß zuordnen und initialisieren, wenn ein Prozess oder Thread an die DLL angefügt wird, um C-Laufzeitdaten ordnungsgemäß zu bereinigen, wenn ein Prozess von der DLL getrennt wird, und für globale C++-Objekte in der DLL ordnungsgemäß konstruiert und destruktiert zu werden.
Die Win32 SDK-Beispiele verwenden alle die erste Methode. Verwenden Sie sie als Beispiel. Weitere Informationen finden Sie in der Win32-Programmierreferenz für DllEntryPoint()
und in der Visual C++-Dokumentation für DllMain()
. Beachten Sie, dass DllMainCRTStartup()
Aufrufe und CRT_INIT()
aufruft CRT_INIT()
die DllMain() Ihrer Anwendung, falls vorhanden.
Wenn Sie die zweite Methode verwenden und den CRT-Initialisierungscode selbst aufrufen möchten, statt ihn zu verwenden DllMainCRTStartup()
, gibt DllMain()
es zwei Techniken:
Wenn keine Eintragsfunktion vorhanden ist, die Initialisierungscode ausführt, geben Sie
CRT_INIT()
als Einstiegspunkt der DLL an. Angenommen, Sie haben NTWIN32 eingeschlossen. MAK, der als @12 definiertDLLENTRY
wird, fügen Sie der Linkzeile-entry:_CRT_INIT$(DLLENTRY)
der DLL die Option hinzu.oder
Wenn Sie über einen eigenen DLL-Einstiegspunkt verfügen, gehen Sie im Einstiegspunkt wie folgt vor:
Verwenden Sie diesen Prototyp für
CRT_INIT()
:BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
Informationen zu
CRT_INIT()
Rückgabewerten finden Sie in der Dokumentation DllEntryPoint. Dieselben Werte werden zurückgegeben.On
DLL_PROCESS_ATTACH
andDLL_THREAD_ATTACH
(see DllEntryPoint in the Win32 API reference for more information on these flags), callCRT_INIT()
, first, before any C Run-time functions are called or any floating-point operations are perform.Rufen Sie ihren eigenen Prozess-/Threadinitialisierungs-/Beendigungscode auf.
Am
DLL_PROCESS_DETACH
undDLL_THREAD_DETACH
, letzten AufrufCRT_INIT()
, nachdem alle C-Laufzeitfunktionen aufgerufen wurden und alle Gleitkommavorgänge abgeschlossen sind.
Achten Sie darauf, alle Parameter des Einstiegspunkts weiterzuleiten CRT_INIT()
; CRT_INIT()
erwartet diese Parameter, sodass die Dinge möglicherweise nicht zuverlässig funktionieren, wenn sie weggelassen werden (insbesondere ist fdwReason erforderlich, um zu bestimmen, ob die Prozessinitialisierung oder Beendigung erforderlich ist).
Nachfolgend finden Sie eine Beispieleinstiegspunktfunktion, die zeigt, wann und wie diese Aufrufe CRT_INIT()
im DLL-Einstiegspunkt ausgeführt werden:
BOOL WINAPI DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason,
LPVOID lpReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH || fdwReason == DLL_THREAD_ATTACH)
if (!_CRT_INIT(hinstDLL, fdwReason, lpReserved))
return(FALSE);
if (fdwReason == DLL_PROCESS_DETACH || fdwReason == DLL_THREAD_DETACH)
if (!_CRT_INIT(hinstDLL, fdwReason, lpReserved))
return(FALSE);
return(TRUE);
}
Notiz
Dies ist nicht erforderlich, wenn Sie verwenden DllMain()
und -entry:_DllMainCRTStartup@12
.
Abschnitt 3: Verwenden von NTWIN32. MAK zur Vereinfachung des Buildprozesses
In NTWIN32 sind Makros definiert. MAK, der verwendet werden kann, um Ihre Makefiles zu vereinfachen und sicherzustellen, dass sie ordnungsgemäß erstellt sind, um Konflikte zu vermeiden. Aus diesem Grund empfiehlt Microsoft dringend, NTWIN32 zu verwenden. MAK und die darin enthaltenen Makros.
Verwenden Sie für die Kompilierung Folgendes: $(cvarsdll) for apps/DLLs using CRT in a DLL
.
Verwenden Sie zum Verknüpfen eine der folgenden Optionen:
$(conlibsdll) for console apps/DLLs using CRT in a DLL
$(guilibsdll) for GUI apps using CRT in a DLL
Abschnitt 4: Probleme bei der Verwendung mehrerer CRT-Bibliotheken
Wenn eine Anwendung, die C-Laufzeitaufrufe ausführt, Links zu einer DLL herstellt, die auch C-Laufzeitaufrufe ausführt, beachten Sie, dass beide mit einer der statisch verknüpften C-Laufzeitbibliotheken (LIBC) verknüpft sind. LIB oder LIBCMT. LIB), die .EXE und DLL verfügen über separate Kopien aller C-Laufzeitfunktionen und globalen Variablen. Dies bedeutet, dass C-Laufzeitdaten nicht zwischen dem .EXE und der DLL gemeinsam genutzt werden können. Einige der Probleme, die als Ergebnis auftreten können, sind:
Übergeben von gepufferten Datenstromhandles von der .EXE/DLL an das andere Modul
Zuordnen des Arbeitsspeichers mit einem C-Laufzeitaufruf in der .EXE/DLL und Neuzuordnung oder Freigeben des Speichers im anderen Modul
Überprüfen oder Festlegen des Werts der globalen Errno-Variable in der .EXE/DLL und erwarten, dass sie im anderen Modul identisch ist. Ein verwandtes Problem wird im entgegengesetzten Modul aufgerufen
perror()
, von dem der C-Laufzeitfehler aufgetreten ist, daperror()
errno verwendet.
Um diese Probleme zu vermeiden, verknüpfen Sie sowohl die .EXE als auch die DLL mit CRTDLL. LIB oder MSVCRT. LIB, mit der sowohl die .EXE als auch die DLL den allgemeinen Satz von Funktionen und Daten verwenden können, die in CRT in einer DLL enthalten sind, und C-Laufzeitdaten wie Datenstromhandles können dann sowohl vom .EXE als auch von der DLL gemeinsam genutzt werden.
Abschnitt 5: Mischen von Bibliothekstypen
Sie können Ihre DLL mit CRTDLL verknüpfen. LIB/MSVCRT. LIB unabhängig davon, mit was Ihre .EXE verknüpft ist, wenn Sie das Mischen von CRT-Datenstrukturen und das Übergeben von CRT-Dateihandles oder CRT FILE*-Zeigern an andere Module vermeiden.
Beim Mischen von Bibliothekstypen beachten Sie Folgendes:
CRT-Dateihandles dürfen nur vom CRT-Modul betrieben werden, das sie erstellt hat.
CRT FILE*-Zeiger dürfen nur vom CRT-Modul betrieben werden, das sie erstellt hat.
Der mit der CRT-Funktion
malloc()
zugewiesene Speicher kann nur vom CRT-Modul freigegeben oder neu zugeordnet werden.
Betrachten Sie das folgende Beispiel, um dies zu veranschaulichen:
- .EXE ist mit MSVCRT verknüpft. BEFREIEN
- DLL A ist mit LIBCMT verknüpft. BEFREIEN
- DLL B ist mit CRTDLL verknüpft. BEFREIEN
Wenn der .EXE ein CRT-Dateihandle mit _create()
oder erstellt, kann dieses Dateihandle nur an _lseek()
die datei .EXE übergeben werden. _close()
_read()
_write()
_open()
Übergeben Sie dieses CRT-Dateihandle nicht an eine der DLL-Dateien. Übergeben Sie kein CRT-Dateihandle, das von der DLL an die andere DLL oder an die .EXE abgerufen wurde.
Wenn DLL A einen Speicherblock zuweist malloc()
, kann nur DLL A aufrufen free()
, _expand()
oder realloc()
um diesen Block zu betreiben. Sie können nicht von DLL A aufrufen malloc()
und versuchen, diesen Block aus dem .EXE oder von DLL B frei zu geben.
Notiz
Wenn alle drei Module mit CRTDLL verknüpft wurden. LIB oder alle drei wurden mit MSVCRT verknüpft. LIb, diese Einschränkungen würden nicht gelten.
Beim Verknüpfen von DLLs mit LIBC. LIB, beachten Sie, dass, wenn es eine möglichkeit gibt, dass eine solche DLL von einem Multithread-Programm aufgerufen wird, die DLL nicht mehrere Threads unterstützt, die gleichzeitig in der DLL ausgeführt werden, was zu großen Problemen führen kann. Wenn es eine Möglichkeit gibt, dass die DLL von Multithread-Programmen aufgerufen wird, stellen Sie sicher, dass Sie sie mit einer der Bibliotheken verknüpfen, die Multithread-Programme (LIBCMT) unterstützen. LIB, CRTDLL. LIB oder MSVCRT. LIB).