Share via


Erreurs potentielles passage d'objets CRT au delà de les limites de DLL

Lorsque vous passez des objets (CRT) runtime C comme les handles de fichiers, des paramètres régionaux, les variables d'environnement dans ou hors d'une DLL (appels de fonction à travers la limite de DLL), un comportement inattendu peut se produire si la DLL, ainsi que les fichiers appelant la DLL, utilisent des copies des bibliothèques CRT.

Un problème relatif peut se produire lorsque vous allouez la mémoire (explicitement avec new ou malloc, ou implicitement avec strdup, strstreambuf::str, etc.) puis passez un pointeur sur une limite de DLL à libérer.Cela peut provoquer une violation d'accès de mémoire ou sont traduits l'altération si la DLL et ses utilisateurs utilisent des copies des bibliothèques CRT.

Un autre symptôme de ce problème peut être une erreur dans la fenêtre Sortie pendant le débogage telles que :

TAS [] : adresse valide spécifiée à RtlValidateHeap (#, #)

Causes

Chaque copie de la bibliothèque CRT a une condition distincte et différent.Fondamentalement, les objets CRT comme les handles de fichiers, les variables d'environnement, puis les paramètres régionaux ne sont valides pour la copie du CRT où ces objets sont alloués ou définis.Lorsqu'une DLL et ses utilisateurs utilisent des copies de la bibliothèque CRT, vous ne pouvez pas passer ces objets CRT à travers la limite de DLL et s'attendre à ce que ils soient pris correctement de l'autre côté.

En outre, étant donné que chaque copie de la bibliothèque CRT a son propre gestionnaire de tas, allouant la mémoire à une bibliothèque CRT et en passant le pointeur sur une limite de DLL à libérer par une copie différente de la bibliothèque CRT est une cause potentielle pour l'altération du tas.

Si vous créez votre DLL afin qu'il passe des objets CRT à travers la limite ou alloue de la mémoire et censé signaler à ce qu'elle soit supprimé depuis l'extérieur de la DLL, vous limitez les utilisateurs de DLL pour utiliser la même copie de la bibliothèque CRT que la DLL.La DLL et ses utilisateurs utilisent la même copie de la bibliothèque CRT uniquement si les deux sont liés à la même version de la DLL CRT.Il peut s'agir d'un problème si vous combinez des applications Visual C++ 5,0 avec les DLL générés par Visual C++ 4,1 ou version antérieure.Étant donné que la version DLL de la bibliothèque CRT utilisée par Visual C++ 4,1 est msvcrt40.dll et celui utilisé par Visual 5,0 est msvcrt.dll, vous ne pouvez pas générer votre application d'utiliser la même copie de la bibliothèque CRT que ces DLL.

Toutefois, il existe une exception.En anglais la version en Anglais américain et d'autres versions localisées pour Windows 2000, par exemple l'Allemand, Français, et le Tchèque, une version de redirecteur du msvcrt40.dll (version 4,20) est livrée.Par conséquent, même si la DLL est lié à msvcrt40.dll et son utilisateur est lié avec msvcrt.dll, vous utilisez toujours la même copie de la bibliothèque CRT car tous les appels qu'msvcrt40.dll sont transférés dans msvcrt.dll.

Toutefois cette version de redirecteur de msvcrt40.dll est pas disponible dans certaines versions localisées Windows 2000, telles que le Japonais, le Coréen, et le Chinois.Ainsi, si votre application cible ces systèmes d'exploitation, vous avez besoin de l'un ou l'autre obtient une version mise à jour de la DLL qui ne s'appuie pas sur msvcrt40.dll ou modifier votre application de ne pas compter sur utiliser la même copie des bibliothèques CRT.Si vous avez développé la DLL, cela signifie le régénérer avec Visual C++ 4,2 ou version ultérieure.S'il s'agit d'une DLL tierce, vous devez contacter votre fournisseur pour une mise à niveau.

notez que cette version DLL redirecteur de msvcrt40.dll (version 4,20) ne peut pas être redistribuée.

Exemple

ms235460.collapse_all(fr-fr,VS.110).gifDescription

Cet exemple passe un handle de fichier sur une limite de DLL.

La DLL et le fichier .exe sont générés avec /MD ; ils partagent une seule copie du CRT.

Si vous régénérez avec /MT afin qu'ils utilisent des copies séparées de CRT, exécuter le test1Main.exe résultant trouve une violation d'accès.

ms235460.collapse_all(fr-fr,VS.110).gifCode

// 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(fr-fr,VS.110).gifCode

// 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(fr-fr,VS.110).gifSortie

this is a string

Exemple

ms235460.collapse_all(fr-fr,VS.110).gifDescription

Cet exemple passe des variables d'environnement sur une limite de DLL.

ms235460.collapse_all(fr-fr,VS.110).gifCode

// 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(fr-fr,VS.110).gifCode

// 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(fr-fr,VS.110).gifSortie

MYLIB has not been set.

Si la DLL et le fichier .exe sont générés avec /MD pour qu'une copie du CRT est utilisée, le programme s'exécute correctement et génère la sortie suivante :

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

Voir aussi

Référence

Fonctionnalités de bibliothèque CRT