Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Uw code kan fouten hebben wanneer u C Runtime-objecten (CRT) doorgeeft, zoals bestandsingangen, landinstellingen en omgevingsvariabelen in of uit een DLL. Functieaanroepen over de DLL-grens kunnen onverwacht gedrag veroorzaken als de DLL en bestanden die in het DLL-bestand worden aangeroepen, verschillende kopieën van de CRT-bibliotheken gebruiken.
Er kan een gerelateerd probleem optreden wanneer u geheugen toewijst (expliciet met new of mallocimpliciet met strdup, strstreambuf::strenzovoort) en vervolgens een aanwijzer doorgeeft over een DLL-grens waar deze wordt vrijgemaakt. Dergelijke aanwijzers kunnen een schending van geheugentoegang of heap-beschadiging veroorzaken als de DLL en de consumenten verschillende kopieën van de CRT-bibliotheken gebruiken.
Een ander symptoom van dit probleem is een fout in het uitvoervenster tijdens het debuggen, zoals HEAP[]: Invalid Address specified to RtlValidateHeap(#,#)
Oorzaken
Elke kopie van de CRT-bibliotheek heeft een afzonderlijke en unieke toestand, die door uw app of DLL in lokale threadopslag wordt bewaard.
CRT-objecten, zoals bestandsgrepen, omgevingsvariabelen en landinstellingen, zijn alleen geldig voor de kopie van de CRT in de app of DLL waarin deze objecten zijn toegewezen of ingesteld. Wanneer een DLL en de clients verschillende kopieën van de CRT-bibliotheek gebruiken, kunt u niet verwachten dat deze CRT-objecten correct worden gebruikt wanneer ze over de DLL-grens worden doorgegeven.
Het geldt met name voor CRT-versies vóór de Universal CRT in Visual Studio 2015 en hoger. Er was een versiespecifieke CRT-bibliotheek voor elke versie van Visual Studio die is gebouwd met Visual Studio 2013 of eerder. Interne implementatiedetails van de CRT, zoals gegevensstructuren en naamconventies, waren verschillend in elke versie. Dynamisch koppelen van code die is gecompileerd voor één versie van de CRT naar een andere versie van de CRT DLL, is nooit ondersteund. Soms zou het werken, maar vanwege geluk in plaats van ontwerp.
Elke kopie van de CRT-bibliotheek heeft een eigen heap-manager. Dit kan leiden tot heap-corruptie als u geheugen toewijst in één CRT-bibliotheek en de pointer doorgeeft over een DLL-grens om te worden vrijgemaakt door een andere kopie van de CRT-bibliotheek. Als uw DLL CRT-objecten over de DLL-grens doorgeeft of geheugen toewijst dat buiten de DLL wordt vrijgemaakt, moeten de clients van de DLL dezelfde versie van de CRT-bibliotheek gebruiken als de DLL.
Het DLL-bestand en de clients gebruiken normaal gesproken dezelfde kopie van de CRT-bibliotheek alleen als beide tijdens het laden zijn gekoppeld aan dezelfde versie van de CRT-DLL. Omdat de DLL-versie van de Universal CRT-bibliotheek die wordt gebruikt door Visual Studio 2015 en hoger nu een centraal geïmplementeerd Windows-onderdeel (ucrtbase.dll) is, is dit hetzelfde voor apps die zijn gebouwd met Visual Studio 2015 en latere versies. Zelfs als de CRT-code identiek is, kunt u echter geen geheugen toewijzen aan een onderdeel dat gebruikmaakt van een andere heap.
Voorbeeld: Bestandshandle doorgeven over DLL-grens
Beschrijving
In dit voorbeeld wordt een bestandshandle doorgegeven over een DLL-grens.
De DLL- en .exe-bestanden zijn gebouwd met /MD, zodat ze één kopie van de CRT delen.
Als u opnieuw compileert met /MT zodat ze afzonderlijke kopieën van de CRT gebruiken, leidt het uitvoeren van de resulterende test1Main.exe tot een toegangsfout.
DLL-bronbestand test1Dll.cpp:
// test1Dll.cpp
// compile with: cl /EHsc /W4 /MD /LD test1Dll.cpp
#include <stdio.h>
__declspec(dllexport) void writeFile(FILE *stream)
{
   char   s[] = "this is a string\n";
   fprintf( stream, "%s", s );
   fclose( stream );
}
Uitvoerbaar bronbestand test1Main.cpp:
// test1Main.cpp
// compile with: cl /EHsc /W4 /MD test1Main.cpp test1Dll.lib
#include <stdio.h>
#include <process.h>
void writeFile(FILE *stream);
int main(void)
{
   FILE  * stream;
   errno_t err = fopen_s( &stream, "fprintf.out", "w" );
   writeFile(stream);
   system( "type fprintf.out" );
}
this is a string
Voorbeeld: Omgevingsvariabelen doorgeven over de DLL-grens
Beschrijving
In dit voorbeeld worden omgevingsvariabelen over een DLL-grens doorgegeven.
DLL-bronbestand test2Dll.cpp:
// test2Dll.cpp
// compile with: cl /EHsc /W4 /MT /LD test2Dll.cpp
#include <stdio.h>
#include <stdlib.h>
__declspec(dllexport) void readEnv()
{
   char *libvar;
   size_t libvarsize;
   /* Get the value of the MYLIB environment variable. */
   _dupenv_s( &libvar, &libvarsize, "MYLIB" );
   if( libvar != NULL )
      printf( "New MYLIB variable is: %s\n", libvar);
   else
      printf( "MYLIB has not been set.\n");
   free( libvar );
}
Uitvoerbaar bronbestand test2Main.cpp:
// test2Main.cpp
// compile with: cl /EHsc /W4 /MT test2Main.cpp test2dll.lib
#include <stdlib.h>
#include <stdio.h>
void readEnv();
int main( void )
{
   _putenv( "MYLIB=c:\\mylib;c:\\yourlib" );
   readEnv();
}
MYLIB has not been set.
Als u zowel de DLL- als EXE-bestanden bouwt met behulp van /MD, zodat slechts één kopie van de CRT wordt gebruikt, wordt het programma uitgevoerd en wordt de volgende uitvoer geproduceerd:
New MYLIB variable is: c:\mylib;c:\yourlib
Zie ook
              C Runtime-bestanden (CRT) en C++ Standaardbibliotheek (STL) .lib