Erros possíveis passar objetos de CRT em limites DLL
Quando você passa o C Runtime (CRT) objetos, como identificadores de arquivo, localidades e variáveis de ambiente dentro ou fora de uma DLL (chamadas de função através do limite da DLL), um comportamento inesperado poderá ocorrer se a DLL, bem como os arquivos que a chamada para a DLL, usam cópias diferentes das bibliotecas CRT.
Um problema relacionado pode ocorrer quando você aloca memória (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 para ser liberado.Isso pode causar uma corrupção de heap ou violação de acesso do memória se a DLL e seus usuários usam diferentes cópias das bibliotecas CRT.
Outro sintoma desse problema pode ser um erro na janela Saída durante a depuração, tais como:
[] HEAP: Endereço inválido para RtlValidateHeap(#,#)
Causas
Cada cópia da biblioteca CRT tem um estado separado e distinto.Como tal, CRT com objetos como, por exemplo, os identificadores de arquivo, variáveis de ambiente, e as localidades são válidas apenas para a cópia do CRT onde esses objetos são alocados ou definir.Quando uma DLL e seus usuários usarem cópias diferentes da biblioteca CRT, você não pode passar esses objetos de CRT através do limite da DLL e espera que eles serem retirados corretamente no outro lado.
Além disso, como cada cópia da biblioteca CRT tem 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 serem liberados pela outra cópia da biblioteca CRT é uma causa potencial para corrupção de heap.
Se você criar sua DLL, para que ele passa de objetos de CRT pelo limite ou aloca memória e espera ser liberado fora a DLL, você pode restringir os usuários DLL para usar a mesma cópia da biblioteca CRT como a DLL.A DLL e seus usuários usam a mesma cópia da biblioteca CRT somente se ambos são vinculados com a mesma versão da DLL CRT.Isso poderia ser um problema se você combinar os aplicativos criados com Visual C++ 5.0 com DLLs que são criadas por 4.1 do Visual C++ ou anterior.Como a versão DLL da biblioteca CRT usada pelo 4.1 do Visual C++ é Msvcrt40. dll e usada pelo Visual 5.0 é Msvcrt. dll, você não pode criar seu aplicativo para usar a mesma cópia da biblioteca CRT como essas DLLs.
No entanto, há uma exceção.Em inglês (EUA) versão e algumas outras versões localizadas do Windows 2000, como, por exemplo, alemão, francês e tcheco, uma versão do Msvcrt40. dll (versão 4.20) encaminhador é fornecido.Como resultado, mesmo que a DLL está vinculada com Msvcrt40. dll e o usuário estiver vinculado com Msvcrt. dll, você ainda está usando a mesma cópia da biblioteca CRT porque todas as chamadas feitas para Msvcrt40. dll são encaminhadas para Msvcrt. dll.
No entanto esta versão de encaminhador do Msvcrt40. dll não está disponível em algumas versões localizadas do Windows 2000, como, por exemplo, japonês, coreano e chinês.Assim, se seu aplicativo destina-se a esses sistemas operacionais, você precisa ao obter uma versão atualizada da DLL que não contam com Msvcrt40. dll ou alteram seu aplicativo não depender usando a mesma cópia das bibliotecas CRT.Se você tiver desenvolvido a DLL, isso significa que sua recriação com Visual C++ 4.2 ou posterior.Se for uma DLL de terceiros, você precisa entrar em contato com seu fornecedor para uma atualização.
Observe que esta versão DLL do 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 compartilhem uma única cópia do CRT.
Se você reconstruir com /MT para que eles usem cópias separadas do CRT, executando os resultados de test1Main.exe resultante de 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 os arquivos DLL e. exe são 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