Delen via


De C-runtime gebruiken

In dit artikel wordt beschreven hoe u de C-runtime gebruikt.

Oorspronkelijke productversie: Visual C++
Oorspronkelijk KB-nummer: 94248

Sectie 1: Er zijn drie vormen van C-runtimebibliotheken (CRT) beschikbaar

Er zijn drie vormen van de C-runtimebibliotheek die wordt geleverd met de Win32 SDK:

  • LIBC. LIB is een statisch gekoppelde bibliotheek voor programma's met één thread.

  • LIBCMT. LIB is een statisch gekoppelde bibliotheek die ondersteuning biedt voor multithreaded programma's.

  • CRTDLL. LIB is een importbibliotheek voor CRTDLL.DLL die ook multithreaded programma's ondersteunt. CRTDLL.DLL zelf maakt deel uit van Windows NT.

Microsoft Visual C++ 32-bits editie bevat deze drie formulieren, maar de CRT in een DLL heet MSVCRT. LIB. Het DLL-bestand is herdistribueerbaar. De naam is afhankelijk van de versie van VC++ (d.w.z. MSVCRT10.DLL of MSVCRT20.DLL). Houd er echter rekening mee dat MSVCRT10.DLL niet wordt ondersteund in Win32s, terwijl CRTDLL. LIB wordt ondersteund op Win32s. MSVCRT20.DLL wordt geleverd in twee versies: een voor Windows NT en de andere voor Win32s.

Sectie 2: Crt-bibliotheken gebruiken bij het bouwen van een DLL

Bij het bouwen van een DLL die gebruikmaakt van een van de C-runtimebibliotheken, om ervoor te zorgen dat de CRT correct is geïnitialiseerd, ofwel

  1. De initialisatiefunctie moet een naam DllMain() hebben en het toegangspunt moet worden opgegeven met de linkeroptie -entry:_DllMainCRTStartup@12

    or

  2. Het toegangspunt van het DLL-bestand moet expliciet worden aangeroepen CRT_INIT() bij proceskoppeling en procesontkoppeling.

Hierdoor kunnen de C-runtimebibliotheken C-runtimegegevens correct toewijzen en initialiseren wanneer een proces of thread wordt gekoppeld aan het DLL-bestand, om C-runtimegegevens correct op te schonen wanneer een proces loskoppelt van het DLL-bestand en voor globale C++-objecten in het DLL-bestand correct worden samengesteld en gedestructeerd.

De Win32 SDK-voorbeelden gebruiken allemaal de eerste methode. Gebruik ze als voorbeeld. Raadpleeg ook de Referentie van Win32 Programmeurs voor DllEntryPoint() en de Visual C++-documentatie voor DllMain(). Houd er rekening mee dat DllMainCRTStartup() aanroepen worden aangeroepen CRT_INIT() en CRT_INIT() de DllMain() van uw toepassing worden aangeroepen als deze bestaat.

Als u de tweede methode wilt gebruiken en de CRT-initialisatiecode zelf wilt aanroepen in plaats van te gebruiken DllMainCRTStartup() en DllMain(), zijn er twee technieken:

  1. Als er geen invoerfunctie is die initialisatiecode uitvoert, geeft u CRT_INIT() op als het toegangspunt van het DLL-bestand. Ervan uitgaande dat u NTWIN32 hebt opgenomen. MAK, die als @12 definieert DLLENTRY , voegt u de optie toe aan de koppelingslijn van het DLL-bestand:-entry:_CRT_INIT$(DLLENTRY)

    or

  2. Als u uw eigen DLL-toegangspunt hebt, gaat u als volgt te werk in het toegangspunt:

    1. Gebruik dit prototype voor CRT_INIT(): BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);

      Zie de documentatie DllEntryPoint voor informatie over CRT_INIT() retourwaarden. Dezelfde waarden worden geretourneerd.

    2. Aan DLL_PROCESS_ATTACH en DLL_THREAD_ATTACH (zie DllEntryPoint in de Win32 API-verwijzing voor meer informatie over deze vlaggen), aanroep CRT_INIT(), eerst voordat C-runtimefuncties worden aangeroepen of eventuele drijvendekommabewerkingen worden uitgevoerd.

    3. Roep uw eigen proces/thread initialisatie/beëindigingscode aan.

    4. Aan DLL_PROCESS_DETACH en DLL_THREAD_DETACH, de aanroep CRT_INIT() laatste, nadat alle C-runtimefuncties zijn aangeroepen en alle drijvendekommabewerkingen zijn voltooid.

Zorg ervoor dat u alle parameters van het invoerpunt doorgeeft CRT_INIT() . CRT_INIT() Verwacht deze parameters, zodat de zaken mogelijk niet betrouwbaar werken als ze worden weggelaten (met name fdwReason is vereist om te bepalen of procesinitialisatie of beëindiging nodig is).

Hieronder ziet u een skeletvoorbeeldinvoerpuntfunctie die laat zien wanneer en hoe u deze aanroepen uitvoert CRT_INIT() in het DLL-toegangspunt:

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);
}

Notitie

Dit is niet nodig als u en DllMain() -entry:_DllMainCRTStartup@12.

Sectie 3: NTWIN32 gebruiken. MAK om het buildproces te vereenvoudigen

Er zijn macro's gedefinieerd in NTWIN32. MAK die kan worden gebruikt om uw makefiles te vereenvoudigen en ervoor te zorgen dat ze correct zijn gebouwd om conflicten te voorkomen. Daarom raadt Microsoft ten zeerste aan om NTWIN32 te gebruiken. MAK en de macro's daarin.

Gebruik voor compilatie: $(cvarsdll) for apps/DLLs using CRT in a DLL.

Gebruik een van de volgende opties voor het koppelen:

  • $(conlibsdll) for console apps/DLLs using CRT in a DLL
  • $(guilibsdll) for GUI apps using CRT in a DLL

Sectie 4: Er zijn problemen opgetreden bij het gebruik van meerdere CRT-bibliotheken

Als een toepassing die C Run-Time-aanroepen maakt, koppelingen maakt naar een DLL die ook C Runtime-aanroepen doet, moet u er rekening mee houden dat als deze beide zijn gekoppeld aan een van de statisch gekoppelde C-runtimebibliotheken (LIBC). LIB of LIBCMT. LIB), de .EXE en DLL hebben afzonderlijke kopieën van alle C Runtime-functies en globale variabelen. Dit betekent dat C-runtimegegevens niet kunnen worden gedeeld tussen de .EXE en het DLL-bestand. Enkele van de problemen die kunnen optreden als gevolg hiervan zijn:

  • Gebufferde stroomgrepen van de .EXE/DLL doorgeven aan de andere module

  • Geheugen toewijzen met een C-runtime-aanroep in de .EXE/DLL en het opnieuw toewijzen of vrijmaken van het geheugen in de andere module

  • Controleer of stel de waarde van de globale errnovariabele in de .EXE/DLL in en verwacht dat deze in de andere module hetzelfde is. Een gerelateerd probleem is het aanroepen perror() in de tegenovergestelde module van waaruit de C-runtimefout is opgetreden, omdat perror() errno wordt gebruikt.

Als u deze problemen wilt voorkomen, koppelt u zowel de .EXE als het DLL-bestand aan CRTDLL. LIB of MSVCRT. LIB, waarmee zowel de .EXE als het DLL-bestand de algemene set functies en gegevens in CRT in een DLL kunnen gebruiken, en C-runtimegegevens, zoals stroomingangen, kunnen vervolgens worden gedeeld door zowel de .EXE als het DLL-bestand.

Sectie 5: Bibliotheektypen combineren

U kunt uw DLL koppelen aan CRTDLL. LIB/MSVCRT. LIB, ongeacht waarmee uw .EXE is gekoppeld als u het combineren van CRT-gegevensstructuren en het doorgeven van CRT-bestandsgrepen of CRT FILE*-aanwijzers naar andere modules vermijdt.

Wanneer u bibliotheektypen mengt, houdt u zich aan het volgende:

  • CRT-bestandsingangen kunnen alleen worden gebruikt door de CRT-module die ze heeft gemaakt.

  • CRT FILE*-aanwijzers kunnen alleen worden gebruikt door de CRT-module die ze heeft gemaakt.

  • Geheugen dat is toegewezen met de functie malloc() CRT, kan alleen worden vrijgemaakt of opnieuw worden toegewezen door de CRT-module die deze heeft toegewezen.

Bekijk het volgende voorbeeld om dit te illustreren:

  • .EXE is gekoppeld aan MSVCRT. LIB
  • DLL A is gekoppeld aan LIBCMT. LIB
  • DLL B is gekoppeld aan CRTDLL. LIB

Als de .EXE een CRT-bestandsgreep maakt met behulp van _create() of _open(), kan deze bestandsingang alleen worden doorgegeven aan _lseek(), _read(), _write(), _close()enzovoort in het .EXE bestand. Geef deze CRT-bestandsingang niet door aan een van beide DLL's. Geef geen CRT-bestandsgreep door die is verkregen van DLL naar de andere DLL of naar de .EXE.

Als DLL A een geheugenblok toewijst met malloc(), kan alleen DLL A aanroepen free(), _expand()of realloc() werken op dat blok. U kunt geen aanroepen malloc() vanuit DLL A en proberen dat blok te verwijderen van de .EXE of van DLL B.

Notitie

Als alle drie de modules zijn gekoppeld aan CRTDLL. LIB of alle drie zijn gekoppeld aan MSVCRT. LIb, deze beperkingen zouden niet van toepassing zijn.

Bij het koppelen van DLL's met LIBC. LIB, houd er rekening mee dat als er een mogelijkheid is dat een dergelijke DLL wordt aangeroepen door een programma met meerdere threads, niet meerdere threads die tegelijkertijd in het DLL-bestand worden uitgevoerd, die grote problemen kunnen veroorzaken. Als er een mogelijkheid is dat de DLL wordt aangeroepen door multithreaded programma's, moet u deze koppelen aan een van de bibliotheken die ondersteuning bieden voor multithreaded programma's (LIBCMT). LIB, CRTDLL. LIB of MSVCRT. LIB).