Potential Errors Passing CRT Objects Across DLL Boundaries
来源:互联网 发布:northwind 样本数据库 编辑:程序博客网 时间:2024/05/02 00:06
When you pass C Run-time (CRT) objects such as file handles, locales, and environment variables into or out of a DLL (function calls across the DLL boundary), unexpected behavior can occur if the DLL, as well as the files calling into the DLL, use different copies of the CRT libraries.
A related problem can occur when you allocate memory (either explicitly with new or malloc, or implicitly with strdup, strstreambuf::str, and so on) and then pass a pointer across a DLL boundary to be freed. This can cause a memory access violation or heap corruption if the DLL and its users use different copies of the CRT libraries.
Another symptom of this problem can be an error in the output window during debugging such as:
HEAP[]: Invalid Address specified to RtlValidateHeap(#,#)
Causes
Each copy of the CRT library has a separate and distinct state. As such, CRT objects such as file handles, environment variables, and locales are only valid for the copy of the CRT where these objects are allocated or set. When a DLL and its users use different copies of the CRT library, you cannot pass these CRT objects across the DLL boundary and expect them to be picked up correctly on the other side.
Also, because each copy of the CRT library has its own heap manager, allocating memory in one CRT library and passing the pointer across a DLL boundary to be freed by a different copy of the CRT library is a potential cause for heap corruption.
If you design your DLL so that it passes CRT objects across the boundary or allocates memory and expects it to be freed outside the DLL, you restrict the DLL users to use the same copy of the CRT library as the DLL. The DLL and its users use the same copy of the CRT library only if both are linked with the same version of the CRT DLL. This could be a problem if you mix applications built with Visual C++ 5.0 with DLLs that are built by Visual C++ 4.1 or earlier. Because the DLL version of the CRT library used by Visual C++ 4.1 is msvcrt40.dll and the one used by Visual 5.0 is msvcrt.dll, you cannot build your application to use the same copy of the CRT library as these DLLs.
However, there is an exception. In US English version and some other localized versions of Windows NT 4.0 and Windows 2000, such as German, French, and Czech, a forwarder version of the msvcrt40.dll (version 4.20)is shipped. As a result, even though the DLL is linked with msvcrt40.dll and its user is linked with msvcrt.dll, you are still using the same copy of the CRT library because all calls made to msvcrt40.dll are forwarded to msvcrt.dll.
However this forwarder version of msvcrt40.dll is not available in Windows 95, Windows 98, Windows Millennium Edition (Me), and some localized versions of Windows NT 4.0 and Windows 2000, such as Japanese, Korean, and Chinese. So, if your application targets these operating systems, you need to either obtain an upgraded version of the DLL that doesn't rely on msvcrt40.dll or alter your application to not rely on using the same copy of the CRT libraries. If you have developed the DLL, this means rebuilding it with Visual C++ 4.2 or later. If it is a third- party DLL, you need to contact your vendor for an upgrade.
Please note that this forwarder DLL version of msvcrt40.dll (version 4.20) cannot be redistributed.
Example
This example passes a file handle across a DLL boundary.
The DLL and .exe file are built with /MD, so they share a single copy of the CRT.
If you rebuild with /MT so that they use separate copies of the CRT, running the resulting test1Main.exe results in an access violation.
// 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
Example
This example passes environment variables across a DLL boundary.
// 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.
If both the DLL and .exe file are built with /MD so that only one copy of the CRT is used, the program runs successfully and produces the following output:
New MYLIB variable is: c:/mylib;c:/yourlib
- Potential Errors Passing CRT Objects Across DLL Boundaries
- passing stl objects across dll boundary
- Sharing Kernel Objects Across Process Boundaries
- Making a Service Available Across Domain Boundaries
- Passing Objects Between Android Activities
- Boundaries
- Java.lang.RuntimeException: Can’t marshal non-Parcelable objects across processes.
- Passing a list of objects from view to controller via jquery ajax(Json(aspx) -> object(C#))
- 在请求之间传递对象(Passing objects from request to request)
- ASP.NET MVC - Passing anonymous objects to MVC views and accessing them using dynamic
- 安装Rose 丢失suite objects.dll
- CRT
- CRT
- CRT
- CRT
- Potential算法
- 跨越DLL边界传递CRT对象潜在的错误
- Building MFC application with /MD[d] (CRT dll version)requir...
- 深入浅出C# 中文版 图文皆译 第四章 类型和引用 page134
- 机遇与挑战
- SQL Server不允许进行远程连接的解决办法.
- Fedora10非官方安装手册
- 21天学通JAVA:类设计的技巧
- Potential Errors Passing CRT Objects Across DLL Boundaries
- Delphi设计模式之单例模式(Singleton Pattern)
- 如何写DLL
- Tomcat 5.5 连接池 CLOB
- 系统经常假死该如何解决
- 人事资料管理
- 如何控制在父子窗体中只打开一次子窗体
- 【转自百度】北京IT培训机构就业率调研
- 开机BIOS语言