Поделиться через


Потенциальные ошибки при передаче объекты через границы библиотека DLL CRT

При передаче c (CRT) объекты времени выполнения, как дескрипторы файлов, языковые стандарты и переменные среды или из библиотеки DLL (вызовы функций через границу DLL), непредвиденная функциональности может произойти, если библиотека DLL, а также файлы при вызове метода в библиотеке DLL, использующих различные копии библиотек CRT.

Связанная проблема может возникнуть при выделении памяти (явно с new OR mallocили неявно с strdup" strstreambuf::strи т д) и затем передайте указатель на границе DLL.Это может привести к нарушению доступа к памяти или повреждение кучи, если библиотека DLL и ее пользователи используют разные копии библиотек CRT.

Другой признак этой проблемы может иметь ошибку в окне вывода во время отладки, например:

КУЧА []. Недопустимый указанный адрес в RtlValidateHeap (" #, #)

Причины

Каждая копия библиотеки CRT имеет отдельно и заданному условию.Таким образом, объекты CRT, как дескрипторы файлов, переменные среды и языковые стандарты допустимы только для копирования CRT, где эти объекты выделены или установлены.Если библиотека DLL и ее пользователи используют разные копий библиотеки CRT, нельзя передать эти объекты через границы CRT DLL и ожидать, что они были правильно скомплектованны вверх на другой стороне.

Кроме того, поскольку каждая копия библиотеки CRT имеет свой собственный диспетчер кучи, выделение памяти в одной библиотеке CRT и передает указатель через границу библиотеки DLL, которая будет освобожден другую копию библиотеки CRT возможной причиной повреждения кучи.

Если разрабатывается библиотека DLL, таким образом, чтобы он передает объекты CRT через границу или выделяет память и ожидает его освобоженным вне библиотеки DLL можно ограничить пользователи библиотеки DLL для использования той же копий библиотеки CRT в виде библиотеки DLL.Библиотека DLL и ее пользователи используют одну и ту же копию библиотеки CRT, только если оба связаны с одной и той же версией библиотеки DLL CRT.Это может быть проблемой, если созданные для смешиваете приложений с помощью Visual C++ 5,0 с библиотекой DLL, которые формируются Visual C++ 4,1 или предыдущие.Поскольку версия библиотеки DLL CRT, используемой библиотеки Visual C++ 4,1 msvcrt40.dll и используется визуальным элементом 5,0 msvcrt.dll, нельзя построить приложение использовать одну копию библиотеки CRT в качестве этих библиотек DLL.

Однако исключение.Английской версии США и в некоторых других локализованных версиях Windows 2000, немецкий, французский и чешский, погружена версия сервера пересылки msvcrt40.dll (версия 4.20).В результате, даже если библиотека DLL, связанные с msvcrt40.dll и его пользователь связан с msvcrt.dll можно по-прежнему использовать ту же копию библиотеки CRT, поскольку все msvcrt40.dll вызываются в переадресованны к msvcrt.dll.

Однако эта версия сервера пересылки msvcrt40.dll недоступна в некоторых локализованных версиях Windows 2000, как японский, корейский и китайский.Поэтому, если приложение предназначен для этих операционных систем, необходимо то появляется обновленную версию библиотеки DLL, не зависящее от msvcrt40.dll или alter приложение не полагаться на использовании одной копии библиотек CRT.Если начинали библиотеки DLL, то это означает перестроить его с Visual C++ 4,2 или более поздней версии.Если это сторонних библиотек DLL, необходимо обратиться к поставщик для обновления.

Обратите внимание, что эту версию DLL сервера пересылки msvcrt40.dll (версия 4.20) нельзя распространять.

Пример

ms235460.collapse_all(ru-ru,VS.110).gifОписание

В этом примере передает дескриптор файла через границу библиотеки DLL.

Библиотека DLL и exe-файла построенные с /MD, поэтому они совместно используют одну копию CRT.

При перестроении с /MT, чтобы они будут использовать отдельные копии CRT, выполнить полученный в результате test1Main.exe Нарушении прав доступа.

ms235460.collapse_all(ru-ru,VS.110).gifКод

// 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(ru-ru,VS.110).gifКод

// 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(ru-ru,VS.110).gifOutput

this is a string

Пример

ms235460.collapse_all(ru-ru,VS.110).gifОписание

В этом примере передает переменные среды через границу библиотеки DLL.

ms235460.collapse_all(ru-ru,VS.110).gifКод

// 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(ru-ru,VS.110).gifКод

// 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(ru-ru,VS.110).gifOutput

MYLIB has not been set.

Если библиотека DLL и exe-файла построенные с /MD, чтобы будет использоваться только одна копия CRT, программа выполняется успешно и выводит следующие результаты:

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

См. также

Ссылки

Функции библиотеки CRT