Errori potenziali che passano oggetti CRT oltre i limiti di DLL

Quando si passano gli oggetti (CRT) di runtime del linguaggio C come un handle di file, le impostazioni locali e variabili di ambiente in o da una DLL (chiamate di funzione oltre il limite della DLL, il comportamento imprevisto può verificarsi se la DLL nonché i file che chiamano nella DLL, utilizzare le copie diverse delle librerie CRT.

Un problema correlato può verificarsi quando viene allocata memoria (spostandosi in modo esplicito con new o malloc, o in modo implicito con strdup, strstreambuf::str, e così via) e quindi passare un puntatore a un limite della DLL da liberare.È possibile che si verifichi una violazione di accesso alla memoria o risolte nel danneggiamento se la DLL e gli utenti utilizzano le copie diverse delle librerie CRT.

Un altro sintomo di questo problema può essere un errore nella finestra di output durante il debug come:

HEAP []: indirizzo non valido specificato a RtlValidateHeap (#, #)

Cause

Ciascuna copia della libreria CRT dispone di uno stato separato e distinto.Di conseguenza, gli oggetti CRT come handle di file, le variabili di ambiente e le impostazioni locali sono validi solo per la copia di CRT in cui questi oggetti vengono allocati o impostati.Quando una DLL e gli utenti utilizzano le copie diverse della libreria CRT, non è possibile passare questi oggetti CRT attraverso il limite di DLL e prevederli da eseguire correttamente l'altro lato.

Inoltre, poiché ogni copia della libreria CRT dispone di un proprio gestore dell'heap, sia stata allocata la memoria in una libreria CRT e il puntatore oltre un limite della DLL da liberare da una copia di un'altra libreria CRT è una causa possibilità di danneggiamento dell'heap.

Se si progetta la DLL in modo che passi gli oggetti CRT oltre il limite o alloca memoria e la preveda da liberare al di fuori della DLL, limitare gli utenti di DLL per utilizzare la stessa copia della libreria CRT della DLL.La DLL e gli utenti utilizzano la stessa copia della libreria CRT solo se entrambi sono collegati con la stessa versione della DLL CRT.Potrebbe esserci un problema se si combinano le applicazioni compilate con Visual C++ 5,0 con le DLL compilati da Visual C++ 4,1 o precedente.Poiché la versione DLL della libreria CRT utilizzata da Visual C++ 4,1 è msvcrt40.dll e quello utilizzato dalla rappresentazione 5,0 è msvcrt.dll, non è possibile compilare l'applicazione utilizzare la stessa copia della libreria CRT di queste DLL.

Tuttavia, si verifica un'eccezione.In inglese la versione l'inglese Stati Uniti e altre versioni localizzate di Windows 2000, ad esempio il tedesco, francese e Lingua, una versione del server d'inoltro di msvcrt40.dll (versione 4,20) viene fornita.Di conseguenza, anche se la DLL ha effettuato l'accesso msvcrt40.dll e il relativo utente collegato a msvcrt.dll, tuttavia si utilizza la stessa copia della libreria CRT perché tutte le chiamate effettuate a msvcrt40.dll inoltrate a msvcrt.dll.

Tuttavia questa versione server di inoltro di msvcrt40.dll non è disponibile in alcune versioni localizzate di Windows 2000, come quello giapponese, il Coreano e cinese.Pertanto, se l'applicazione è destinata a questi sistemi operativi, è necessario disporre dell'assoluto o relativo viene visualizzata una versione aggiornata della DLL che non si basa su msvcrt40.dll o modificati l'applicazione non basarsi sull'utilizzo della stessa copia delle librerie CRT.Se è stata compilata la DLL, questo significa ricompilato con Visual C++ 4,2 o successiva.Se è una DLL di terze parti, è necessario contattare il fornitore per un aggiornamento.

si noti che questa versione della DLL del server di inoltro di msvcrt40.dll (versione 4,20) non può essere ridistribuito.

Esempio

ms235460.collapse_all(it-it,VS.110).gifDescrizione

In questo esempio viene passato un handle di file attraverso i limiti di una DLL.

La DLL e il file EXE vengono compilati con /MD, in modo che condividono una sola copia di CRT.

Se si ricompila con /MT in modo che vengano utilizzate le copie separate di CRT, eseguire il test1Main.exe risultante è una violazione di accesso.

ms235460.collapse_all(it-it,VS.110).gifCodice

// test1Dll.cpp
// compile with: /MD /LD
#include <stdio.h>
__declspec(dllexport) void writeFile(FILE *stream)
{
   char   s[] = "this is a string\n";
   fprintf( stream, "%s", s );
   fclose( stream );
}

ms235460.collapse_all(it-it,VS.110).gifCodice

// test1Main.cpp
// compile with: /MD 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" );
}

ms235460.collapse_all(it-it,VS.110).gifOutput

this is a string

Esempio

ms235460.collapse_all(it-it,VS.110).gifDescrizione

In questo esempio viene passata le variabili di ambiente oltre i limiti di una DLL.

ms235460.collapse_all(it-it,VS.110).gifCodice

// test2Dll.cpp
// compile with: /MT /LD
#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 );
}

ms235460.collapse_all(it-it,VS.110).gifCodice

// test2Main.cpp
// compile with: /MT /link test2dll.lib
#include <stdlib.h>
#include <stdio.h>

void readEnv();

int main( void )
{
   _putenv( "MYLIB=c:\\mylib;c:\\yourlib" );
   readEnv();
}

ms235460.collapse_all(it-it,VS.110).gifOutput

MYLIB has not been set.

Se la DLL e per il file EXE vengono compilati con /MD in modo che solo utilizzare una copia di CRT, il programma viene eseguito correttamente e produce l'output seguente:

New MYLIB variable is: c:\mylib;c:\yourlib

Vedere anche

Riferimenti

Funzionalità della libreria CRT