잠재적 오류 개체 CRT DLL 경계를 넘어 전달
C 전달할 때 런타임 (CRT) 파일 핸들, 로켈 및 환경 변수 등의 DLL (DLL 경계 함수 호출) CRT 라이브러리의 다른 복사본을 사용 하는 DLL을 호출 하 여 파일 뿐만 아니라 DLL을 예기치 않은 문제가 발생할 수 있습니다 개체입니다.
메모리를 할당할 때에 관련 된 문제가 발생할 수 있습니다 (명시적으로 new 또는 malloc, 암시적으로 또는 strdup, strstreambuf::str등) 다음 DLL 경계에서 해제 될 때까지 포인터를 전달 합니다.CRT 라이브러리의 다른 복사본은 DLL 및 사용자 사용 하는 경우이 메모리 액세스 위반이 나 힙 손상이 발생할 수 있습니다.
이 문제의 또 다른 현상으로 디버깅 하는 동안 출력 창에서에서 오류를 사용할 수 있습니다.
힙: Rtlvalidateheap(#,#)에 지정 된 주소가 잘못 되었습니다.
원인
CRT 라이브러리의 각 복사본에 서로 다른 상태가 되었습니다.CRT 파일 핸들, 환경 변수 등을 개체 및 로케일만 이러한 개체 설정 하거나 됩니다 할당 된 CRT의 복사본에 대 한 잘못 된.CRT 라이브러리의 다른 복사본은 DLL 및 사용자 사용 하는 경우 이러한 CRT 개체 DLL 경계를 넘어 전달 하 고 정확 하 게 다른 쪽을 선택 하도록 의도 수 없습니다.
CRT 라이브러리의 각 복사본이 해당 힙 관리자 있기 때문에 CRT 라이브러리에서 메모리를 할당 하 고 포인터를 전달 하 여 CRT 라이브러리의 다른 복사본에서 해제 될 때까지 DLL 경계에서 힙 손상에 대 한 잠재적 원인 이기도 합니다.
여 CRT 개체의 경계를 넘어 전달 또는 메모리를 할당 하 고 해당 DLL 외부에서 해제 될 때까지 필요한 DLL을 디자인 하는 경우 DLL로 CRT 라이브러리의 동일한 복사본을 사용 하는 DLL 사용자를 제한 합니다.DLL 및 사용자 모두 동일한 버전의 CRT DLL에만 연결 하려면 CRT 라이브러리의 동일한 복사본을 사용 합니다.Visual C++ 5.0 또는 이전 버전에서 Visual C++ 4.1 빌드된 Dll과 함께 작성 된 응용 프로그램을 함께 사용할 경우 문제가 될 수 있습니다.Visual C++ 4.1에서 사용 되는 CRT 라이브러리의 DLL 버전 msvcrt40.dll 고 msvcrt.dll 비주얼 5.0에서 사용 하는 것입니다 때문에 이러한 Dll로 CRT 라이브러리의 동일한 복사본을 사용 하도록 응용 프로그램을 빌드할 수 없습니다.
그러나, 예외가 있습니다.독일어, 프랑스어, 체코어, 전달자 버전의 msvcrt40.dll (버전 4.20) 함께 출하 된 것과 같이 영어 (미국)에서 버전 및 다른 버전의 Windows 2000 지역화.Msvcrt.dll을 msvcrt40.dll에 대 한 모든 호출을 전달 하기 때문에 결과적으로 DLL msvcrt40.dll로 연결 되 고 해당 사용자가 msvcrt.dll에 링크 된에, 여전히 CRT 라이브러리의 동일한 복사본을 사용 됩니다.
그러나이 전달자 버전의 msvcrt40.dll Windows 2000 일본어, 한국어, 중국어 등의 일부 언어 버전에서 사용할 수 없습니다.따라서 응용 프로그램이 이러한 운영 체제를 대상으로 하는 경우에 업그레이드 된 버전의 msvcrt40.dll에 의존 하거나 CRT 라이브러리의 동일한 복사본을 사용 하 여 사용 하지 않는 응용 프로그램을 변경 하지 않는 DLL 얻이 필요 합니다.DLL 개발한 경우 Visual C++ 4.2 또는 나중에 다시 의미 합니다.공급 업체 DLL의 경우 업그레이드 공급 업체에 문의 해야 합니다.
이 전달자 DLL 버전의 msvcrt40.dll (버전 4.20)을 재배포 될 수 없으며 note 하십시오.
예제
설명
이 예제에서는 DLL 경계에서 파일 핸들을 전달합니다.
DLL 및.exe 파일이 만들어집니다 /MD, CRT의 단일 복사본을 공유 하므로.
CRT의 별도 복사본을 사용할 수 있도록 mt를 사용 하 여 다시 빌드하는 경우 액세스 위반을 결과 test1Main.exe 결과 실행 합니다.
코드
// 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 );
}
코드
// 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" );
}
Output
this is a string
예제
설명
이 예제에서는 DLL 경계에서 환경 변수를 전달합니다.
코드
// 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 );
}
코드
// 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();
}
Output
MYLIB has not been set.
CRT의 복사본을 하나만 사용 하는 DLL 및.exe 파일을 빌드하면 프로그램이 성공적으로 실행 하 고 다음과 같이 출력 됩니다.
New MYLIB variable is: c:\mylib;c:\yourlib