再次温习运行时库

【摘抄】

来源msdn:

C Run-Time Libraries

This topic discusses the various .lib files that comprise the C run-time libraries as well as their associated compiler options and preprocessor directives.

The following libraries contain the C run-time library functions.

C run-time library (without iostream or standard C++ library) Characteristics Option Preprocessor directives
LIBC.LIB Single-threaded, static link /ML  
LIBCMT.LIB Multithreaded, static link /MT _MT
MSVCRT.LIB Multithreaded, dynamic link (import library for MSVCR71.DLL). Be aware that if you use the Standard C++ Library, your program will need MSVCP71.DLL to run. /MD _MT, _DLL
LIBCD.LIB Single-threaded, static link (debug) /MLd _DEBUG
LIBCMTD.LIB Multithreaded, static link (debug) /MTd _DEBUG, _MT
MSVCRTD.LIB Multithreaded, dynamic link (import library for MSVCR71D.DLL) (debug) /MDd _DEBUG, _MT, _DLL

If you link your program from the command line without a compiler option that specifies a C run-time library, the linker will use LIBC.LIB.

To build a debug version of your application, the _DEBUG flag must be defined and the application must be linked with a debug version of one of these libraries. For more information about using the debug versions of the library files, see CRT Debugging Techniques.

This version of Visual C++ is not conformant with the C99 standard.

Standard C++ Library

Note that starting in Visual Studio .NET 2003, Visual C++ will no longer ship the old iostream libraries. For details, see Upgrade to the Standard C++ Library and the Standard C++ Library Overview.

The new iostream functions, as well as many other new functions, exist in the Standard C++ Library:

Standard C++ Library Characteristics Option Preprocessor directives
LIBCP.LIB Single-threaded, static link /ML  
LIBCPMT.LIB Multithreaded, static link /MT _MT
MSVCPRT.LIB Multithreaded, dynamic link (import library for MSVCP71.dll) /MD _MT, _DLL
LIBCPD.LIB Single-threaded, static link /MLd _DEBUG
LIBCPMTD.LIB Multithreaded, static link /MTd _DEBUG, _MT
MSVCPRTD.LIB Multithreaded, dynamic link (import library for MSVCP71D.DLL) /MDd _DEBUG, _MT, _DLL

When you build a release version of your project, one of the basic C run-time libraries (LIBC.LIB, LIBCMT.LIB, and MSVCRT.LIB) is linked by default, depending on the compiler option you choose (single-threaded, multithreaded, or DLL). If you include a Standard C++ Library header in your code, a Standard C++ Library will be linked in automatically by Visual C++ at compile time. For example:

#include <ios> 

What is the difference between msvcrt.dll and msvcr71.dll?

The msvcrt.dll is now a "known DLL," meaning that it is a system component owned and built by Windows. It is intended for future use only by system-level components. An application should use and redistribute msvcr71.dll, and it should avoid placing a copy or using an existing copy of msvcr71.dll in the system directory. Instead, the application should keep a copy of msvcr71.dll in its application directory with the program executable. Any application built with Visual C++ .NET using the /MD switch will necessarily use msvcr71.dll.

What problems exist if an application uses both msvcrt.dll and msvcr71.dll?

If you have a .lib or .obj file that needs to link to msvcrt.lib, then you should not have to recompile it to work with the new msvcrt.lib in Visual C++ .NET. The .lib or .obj file may rely on the sizes, field offsets, or member function names of various CRT classes or variables, and those should all still exist in a compatible way. When you relink against msvcrt.lib, your final EXE and DLL image will now have a dependency on msvcr71.dll instead of msvcrt.dll.

If you have more than one DLL or EXE, then you may have more than one CRT, whether or not you are using different versions of Visual C++. For example, statically linking the CRT into multiple DLLs can present the same problem. Developers encountering this problem with static CRTs have been instructed to compile with /MD to use the CRT DLL. Now that the CRT DLL has been renamed to msvcr71.dll, applications may have some components linked to msvcrt.dll and others to msvcr71.dll. If your DLLs pass CRT resources across the msvcrt.dll and msvcr71.dll boundary, you will encounter issues with mismatched CRTs and need to recompile your project with Visual C++ .NET.

【实践】
设想如下:
一个基础的计算封装成静态库文件
一个动态库文件引用静态库文件,再次封装静态库文件的函数对外
一个测试应用分别调用两类库文件
代码如下:
静态库
MathFun.h
1 #ifndef _MATHFUN_H_
2  #define _MATHFUN_H_
3
4  int AddNum(const int& a ,const int& b);
5
6  #endif

MathFun.cpp
#include "stdafx.h"
#include
"MathFun.h"

int AddNum(const int& a ,const int& b)
{
return a+b;
}
动态库
dll.h
1 #ifdef DLL_EXPORTS
2  #define DLL_API __declspec(dllexport)
3  #else
4  #define DLL_API __declspec(dllimport)
5  #endif
6
7 DLL_API int AddNumber(int a ,int b);
dll.cpp
1 // dll.cpp : 定义 DLL 应用程序的入口点。
2  //
3  
4 #include "stdafx.h"
5 #include "dll.h"
6
7 #include "../LibMath/MathFun.h"
8  #pragma comment(lib ,"../debug/LibMath.lib")
9
10 #ifdef _MANAGED
11  #pragma managed(push, off)
12  #endif
13
14 BOOL APIENTRY DllMain( HMODULE hModule,
15 DWORD ul_reason_for_call,
16 LPVOID lpReserved
17 )
18 {
19 switch (ul_reason_for_call)
20 {
21 case DLL_PROCESS_ATTACH:
22 case DLL_THREAD_ATTACH:
23 case DLL_THREAD_DETACH:
24 case DLL_PROCESS_DETACH:
25 break;
26 }
27 return TRUE;
28 }
29
30 #ifdef _MANAGED
31  #pragma managed(pop)
32  #endif
33
34 DLL_API int AddNumber(int a ,int b)
35 {
36 return AddNum(a ,b);
37 }
测试应用
调用静态库
1 // TestLibrary.cpp : 定义控制台应用程序的入口点。
2  //
3  
4 #include "stdafx.h"
5
6 #include "../LibMath/MathFun.h"
7  #pragma comment(lib ,"../debug/LibMath.lib")
8
9  int _tmain(int argc, _TCHAR* argv[])
10 {
11 int ret = AddNum(23,100);
12
13 printf("%d\n" ,ret);
14
15 ret = getchar();
16
17 return 0;
18 }
调用动态库
1 // TestLibrary.cpp : 定义控制台应用程序的入口点。
2  //
3  
4 #include "stdafx.h"
5
6  int _tmain(int argc, _TCHAR* argv[])
7 {
8 typedef int(*pAddNum)(int a,int b);
9 HINSTANCE hDLL;
10 pAddNum anum;
11 hDLL=LoadLibrary(L"DLL.dll");//加载动态链接库DLL.dll文件;
12   anum=(pAddNum)GetProcAddress(hDLL,"AddNumber");
13 int ret = anum(5,8);
14 FreeLibrary(hDLL);//卸载MyDll.dll文件;
15  
16 printf("%d\n" ,ret);
17
18 ret = getchar();
19
20 return 0;
21 }
一般情况下,调用动态的时候需要判断,下面给出一个常用
1 // TestLibrary.cpp : 定义控制台应用程序的入口点。
2  //
3
4 #include "stdafx.h"
5
6 int _tmain(int argc, _TCHAR* argv[])
7 {
8 int ret = 0 ;
9
10 typedef int(*pAddNum)(int a,int b);
11 HINSTANCE hDLL;
12 pAddNum anum;
13 hDLL=LoadLibrary(L"DLL.dll");//加载动态链接库DLL.dll文件;
14 if (hDLL != NULL)
15 {
16 anum=(pAddNum)GetProcAddress(hDLL,"AddNumber");
17 if (anum != NULL)
18 ret = anum(5,8);
19 }
20 FreeLibrary(hDLL);//卸载MyDll.dll文件;
21
22 printf("%d\n" ,ret);
23
24 ret = getchar();
25
26 return 0;
27 }

【尽量组合运行时库来验证,如下】

调用静态库
结论:
静态库mtd,测试mdd出现2个警告,其来源于两个使用运行时库文件不一致
静态库mdd,测试mdd,完全通过,无警告;同样,两个设置成为mtd,也完全通过
静态库mdd,测试mtd,错误信息

调用动态库
结论:
静态库mtd,动态mdd,测试mdd,编译通过,运行错误
静态库mdd,动态mdd,测试mdd,编译通过,运行成功(全部mtd也一样,区别在于生成文件大小,前者小很多)
静态库mdd,动态mtd,测试mdd,编译dll就通不过
【建议】
1、使用相同的运行时库来编译所有项目!!
2、尽量用动态库文件,其运行时库最好采用MD
3、静态库文件,其运行时库也采用MD
Ps:vs2005默认建立这两类项目采用的是MD/MDd
在调试dll的时候有一个错误,const char[]转为LPCTSTR,不能直接使用(WCHAE *)转换,会出现乱码~因为当前编译器默认unicode字符类型~由于本测试用的字符串常量,那么可以使用L""来处理了~如果是变量,建议使用MultiByteToWideChar函数~
另外:在windows下查看dll有什么函数,可以使用depends.exe工具
posted @ 2011-03-10 13:39  西就东城  阅读(432)  评论(0编辑  收藏  举报