Potential errors in passing CRT objects across DLL boundaries
Translation: Magictong (Tong Lei) May 2013
Copyright: Microsoft
Original address: http://msdn.microsoft.com/en-us/library/ms235460 (v=vs.80). aspx
Brief introduction
When you pass a C run-time (CRT) object (such as a file handle, locale, environment variable, and so on) to the outgoing DLL (by calling some of the functions exposed in the DLL), if the DLL loads a different CRT library than the executable, you may find something that is not intentional.
There is one that you may have encountered, similar to the problem that if the executable program allocates a piece of memory outside (shown by new or malloc allocations, or by calling Strdup,strstreambuf::str, etc., the implicit allocation of functions), The allocated memory pointer is then passed into the DLL by invoking the function exposed by the DLL, and if the DLL loads a different CRT library, it may cause memory access violation (AV) or heap corruption.
If you are debugging a program, this problem may print an error message in the Debug Output window as follows:
Heap[]: Invalid Address specified to Rtlvalidateheap (#,#)
Reason
Replicas of each CRT library have a separate and unique state, so CRT objects such as file handles, locales, and environment variables are only valid in the CRT library that allocates it or sets it. When a DLL and the program using this DLL are using two different CRT libraries, if you pass these CRT objects to each other on both the DLL and the program that uses the DLL, and you want the program to run normally, it is unlikely.
In addition, because each copy of the CRT library has its own heap manager, the allocation of memory in one CRT library (by invoking a function exposed by the DLL) to another CRT library may lead to heap corruption.
If you want to design a DLL that can pass the CRT object, or explicitly allocate memory inside the DLL, and release it outside the DLL, you must restrict the user of this DLL to use the same CRT library as the DLL. Instead, users of DLLs use the same CRT libraries as DLLs unless they are linked to the same version of the CRT dynamic-link library. If the application and DLL are compiled differently, for example, the application uses Visual c++5.0 compilation and the DLL uses Visual C + + 4.1 compilation or earlier, because the CRT libraries used by Visual C + + 4.1 are Msvcrt40.dll, and the visual c++5.0 is using Msvcrt.dll, which can be very cumbersome. You may not be able to recompile your application so that it is identical to the CRT library used by the DLL.
However, there is a special case. In some special versions of Windows NT 4.0 and Windows 2000 (for example, the American English version, Germany, France and the Czech Republic localized versions), a proxy mode of Msvcrt40.dll was used (the specific version is 4.20). In these environments, Although the DLL is linked to the Msvcrt40.dll,dll user (application) link is msvcrt.dll, but because all calls to Msvcrt40.dll are transferred to the Msvcrt.dll, this situation is still using the same CRT library.
However, this proxy version of Msvcrt40.dll in Windows 95,windows 98,windows me and some other localized Windows NT 4.0 and Windows 2000 (such as Japanese, Korean, and Chinese) versions are not valid. Therefore, if your application's target operating system is these environments, you need to obtain an upgraded version of the DLL that does not rely on Msvcrt40.dll, or change your application. If you have already developed this DLL, then recompile the DLL with Visual C + + 4.2 or later, if the DLL is a third-party provided component, you may need to provide an upgrade for the relevant developer.
Example One
Describe
Here is an instance of passing a file handle across a DLL boundary.
if DLL files and. exe files are compiled using/MD, then they use the same copy of the CRT library, which is fine.
If you use/MT to recompile so that they use a different CRT library and then run Test1Main.exe, an access violation (access violation) immediately occurs.
Code
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);
}
Code
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
Example Two
Describe
This example illustrates the issue of passing environment variables across DLLs.
Code
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 have not been set.\n");
Free (Libvar);
}
Code
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 ();
}
If both the DLL and the. exe file are compiled using/MD, then both use the same copy of the CRT library, when the output is new Mylib variable is:c:\mylib;c:\yourlib, and if both are compiled with/MT, the output will be Mylib has not been set.
(Note: The above two instances, translator Magictong has not been tested, if there is a problem, please tell Magictong)
Reference documents
C Run-Time library http://msdn.microsoft.com/en-us/library/abx4dbyh (v=vs.100). aspx
http://blog.csdn.net/magictong/article/details/8927049
Potential errors in passing CRT objects across DLL boundaries