Udostępnij za pośrednictwem


Potencjalnych błędów, przekazując obiektów CRT granicami DLL

Po przesunięciu C Run-time (CRT) obiektów takich jak dojścia do plików, ustawień regionalnych i zmiennych środowiskowych do lub z biblioteki DLL (wywołania funkcji granice DLL), nieoczekiwane zachowanie może wystąpić, jeśli biblioteki DLL, jak również plików, wywołanie do biblioteki DLL, należy użyć różnych egzemplarzy bibliotek CRT.

Pokrewny problem może wystąpić podczas przydzielania pamięci (albo jawnie z new lub malloc, lub niejawnie z strdup, strstreambuf::str, i tak dalej), a następnie przebieg wskaźnik granice biblioteki DLL, aby zostać uwolnione.To może spowodować uszkodzenie pamięci dostępu naruszenie lub sterty biblioteki DLL i jej użytkowników należy używać różnych egzemplarzy bibliotek CRT.

Innym symptomem tego problemu może być błąd w oknie output podczas debugowania, takie jak:

[] STOSU: Nieprawidłowy adres określonego do RtlValidateHeap(#,#)

Powoduje, że

Każda kopia biblioteki CRT ma Państwo odrębne i niezależne.Jako takie CRT obiekty takie jak dojścia do plików, zmienne środowiskowe i ustawienia regionalne są prawidłowe dla kopii CRT, gdzie te obiekty są przydzielone lub ustawić tylko.Biblioteki DLL i jej użytkownikom korzystania z różnych egzemplarzy biblioteki CRT, nie można przekazać te obiekty CRT granice DLL i powinny być zabierani poprawnie po drugiej stronie.

Ponieważ każdy egzemplarz biblioteki CRT ma swój własny menedżera sterty, przydzielania pamięci w jednej bibliotece CRT i przekazując wskaźnik granice DLL być zwalniane przez inną kopię biblioteki CRT jest również potencjalne przyczyny uszkodzenia sterty.

Podczas projektowania biblioteki DLL, który przekazuje CRT obiektów przez granice lub przydziela pamięć i oczekuje ona zwolniona poza biblioteki DLL, można ograniczyć użytkownicy biblioteki DLL, aby użyć tej samej kopii biblioteki CRT jako biblioteki DLL.Biblioteki DLL i jej użytkowników należy używać tej samej kopii biblioteki CRT tylko wtedy, gdy obie są połączone z tą samą wersją biblioteki DLL CRT.Może to być problem, jeśli wymieszać aplikacji utworzonych za pomocą programu Visual C++ wersji 5.0, z biblioteki DLL, które są wbudowane w Visual C++ 4.1 lub wcześniejszych.Ponieważ wersja DLL biblioteki CRT używane przez program Visual C++ 4.1 jest msvcrt40.dll i używany przez Visual 5.0 jest msvcrt.dll, nie może zbudować przebudować aplikację za pomocą tej samej kopii biblioteki CRT jako tych bibliotek DLL.

Jednakże jest wyjątek.W nas angielskiej wersji i niektóre inne zlokalizowane wersje systemu Windows 2000, takich jak niemiecki, francuski i czeski, wersja usługi przesyłania dalej msvcrt40.dll (wersja 4.20) jest wysyłany.W związku z powyższym nawet, jeśli biblioteka DLL jest związane z msvcrt40.dll i jego użytkownik jest połączony z msvcrt.dll, wciąż używasz tej samej kopii biblioteki CRT, ponieważ wszystkie wywołania msvcrt40.dll są przesyłane dalej do msvcrt.dll.

Jednak ta wersja usługi przesyłania dalej msvcrt40.dll nie jest dostępny w zlokalizowanych wersjach systemu Windows 2000, takich jak japoński, koreański i chiński.Tak Jeśli aplikacja jest przeznaczony dla tych systemów operacyjnych, należy albo uzyskaliśmy uaktualnionej wersji biblioteki DLL, która nie polegać na msvcrt40.dll lub zmieniać aplikacji nie polegać na przy użyciu tej samej kopii biblioteki CRT.Jeśli rozwinęły się biblioteki DLL, oznacza to, przebudowa, Visual C++ 4.2 lub później.Jeśli biblioteka DLL strony trzeciej, należy skontaktować się z dostawcą w celu dokonania uaktualnienia.

Uwaga: nie można redystrybuować tej wersji biblioteki DLL usługi przesyłania dalej msvcrt40.dll (wersja 4.20).

Przykład

ms235460.collapse_all(pl-pl,VS.110).gifOpis

W tym przykładzie przechodzi uchwyt pliku granice biblioteki DLL.

Plik DLL i exe są budowane z opcje, tak posiadają pojedynczą kopię CRT.

Po odbudowaniu się z /MT, tak aby były używane w oddzielnych kopiach CRT, uruchomiony wynikowy wyniki test1Main.exe powoduje naruszenie zasad dostępu.

ms235460.collapse_all(pl-pl,VS.110).gifKod

// 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(pl-pl,VS.110).gifKod

// 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(pl-pl,VS.110).gifDane wyjściowe

this is a string

Przykład

ms235460.collapse_all(pl-pl,VS.110).gifOpis

W tym przykładzie przekazuje zmiennych środowiskowych, granice biblioteki DLL.

ms235460.collapse_all(pl-pl,VS.110).gifKod

// 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(pl-pl,VS.110).gifKod

// 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(pl-pl,VS.110).gifDane wyjściowe

MYLIB has not been set.

Jeśli pliku bibliotekę DLL i exe są zbudowane z opcje tak, że używana jest tylko jedna kopia CRT, program jest uruchamiany pomyślnie i generuje następujący wynik:

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

Zobacz też

Informacje

Funkcje biblioteki CRT