Compartilhar via


Erros potenciais passar objetos CRT em limites DLL

Quando você passar o C Runtime (CRT) objetos, sistema autônomo identificadores de arquivo, localidades e variáveis de ambiente dentro ou para fora de uma DLL (chamadas de função entre o limite da DLL), comportamentos inesperados podem ocorrer se a DLL, bem sistema autônomo sistema autônomo arquivos a chamada para a DLL usam diferentes cópias das bibliotecas CRT.

Um problema relacionado pode ocorrer quando você aloca memória (seja explicitamente com new ou malloc, ou implicitamente com strdup, strstreambuf::stre assim por diante) e, em seguida, passar um ponteiro em um limite de DLL a ser liberado. Isso pode causar uma corrupção de memória acesso violação ou heap se a DLL e seus usuários usam diferentes cópias das bibliotecas CRT.

Outro sintoma desse problema pode ser um erro na janela de saída durante a depuração, sistema autônomo:

[] DE PILHA: Endereço inválido especificado para RtlValidateHeap(#,#)

Faz com que

Cada cópia da biblioteca CRT tem um estado separado e distinto.Assim, CRT objetos sistema autônomo identificadores de arquivo, sistema autônomo variáveis de ambiente, e sistema autônomo localidades são somente válidas para a cópia do CRT em que esses objetos são alocados ou conjunto.Quando uma DLL e seus usuários usarem cópias diferentes da biblioteca CRT, não é possível passar esses objetos CRT entre o limite da DLL e espera que eles deve ser separado corretamente no Outros lado.

Além disso, como cada cópia da biblioteca CRT possui seu próprio Gerenciador de heap, alocação de memória em uma biblioteca do CRT e passar o ponteiro em um limite de DLL a ser liberados por uma cópia diferente da biblioteca CRT é uma causa potencial para corrupção de pilha.

Se você criar sua DLL, para que ele passa objetos CRT entre o limite ou aloca memória e espera ser liberado fora a DLL, você restringir sistema autônomo usuários DLL para usar a mesma cópia da biblioteca CRT sistema autônomo a DLL.A DLL e seus usuários usar a mesma cópia da biblioteca CRT somente se ambos são vinculados com a mesma versão da CRT DLL.Isso pode ser um problema se você combinar os aplicativos criados com Visual C++ 5.0 com DLLs que são criadas pelo Visual C++ 4.1 ou anterior.Porque a versão da DLL da biblioteca CRT usada pelo Visual C++ 4.1 é msvcrt40.dll e usada pelo Visual 5.0 é msvcrt.dll, não é possível criar seu aplicativo para usar a mesma cópia da biblioteca CRT sistema autônomo essas DLLs.

No entanto, há uma exceção.Em inglês dos EUA versão e alguns outros versões localizadas do Windows 2000, sistema autônomo alemão, francês e tcheco, uma versão encaminhador do msvcrt40.dll (versão 4.20) é fornecido.sistema autônomo resultado, mesmo que a DLL está vinculada msvcrt40.dll e o usuário está vinculado msvcrt.dll, você ainda está usando a mesma cópia da biblioteca CRT porque todas sistema autônomo chamadas feitas para msvcrt40.dll são encaminhadas para msvcrt.dll.

No entanto, esta versão do encaminhador do msvcrt40.dll não está disponível em algumas versões localizadas do Windows 2000, sistema autônomo japonês, coreano e chinês.Assim, se seu aplicativo tem como alvo desses sistemas operacionais, você precisa ao obter uma versão atualizada da DLL que não contam com msvcrt40.dll ou alterar seu aplicativo não depender da usando a mesma cópia das bibliotecas CRT.Se você tiver desenvolvido a DLL, isso significa recriando-lo com o Visual C++ 4.2 ou posterior.Se for uma DLL de terceiros, você precisará entre em contato com seu fornecedor para obter uma atualização.

Observe que esta versão da DLL de encaminhador do msvcrt40.dll (versão 4.20) não pode ser redistribuído.

Exemplo

Descrição

Este exemplo passa um identificador de arquivo em um limite de DLL.

O arquivo DLL e exe são construídos com /MD, para que eles compartilham uma única cópia do CRT.

Se você recompilar com /MT para que eles usem cópias separadas do CRT, sendo executado os resultados test1Main.exe resultante em uma violação de acesso.

Código

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

Código

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

Saída

this is a string

Exemplo

Descrição

Este exemplo passa variáveis de ambiente em um limite de DLL.

Código

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

Código

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

Saída

MYLIB has not been set.

Se a DLL e EXE arquivo é construído com /MD para que somente uma cópia do CRT é usada, o programa seja executado com êxito e produz a seguinte saída:

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

Consulte também

Referência

C em time de execução bibliotecas