关于VC2005的一个变态的问题。目前在多个地方被这个问题困扰:
a、采用MFC Shared DLL方式编译出来的程序拷贝到测试部门会出现问题。所以只能采用静态DLL方式,但这导致
DLL变得太大。
b、内存泄漏、溢出检测时,需要使用MSVCR80.dll的函数,但是采用LoadLibrary的方式也会出现这个问题。
这个问题是:程序报R6034的严重警告。
解决了这个问题,发现以下一些经验:
a、VC2005采用Manifest文件来管理动态库的版本,防止动态库升级引发的“DLL HELL”。
b、分为两种情况:
(一)系统加载动态库。
当系统要加载某DLL时,系统首先检索系统目录,再到当前目录寻找Manifest文件。
如果在某个Manifest文件中找到该DLL,则加载该DLL。
(所以如果没有把Manifest文件拷贝到目标电脑上,而且放在当前目录或者系统目录下的话,
程序加载时出错。注意,不是把x86_Microsoft.VC80.DebugCRT_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_f75eb16c
整个文件夹拷贝过去,需要把里面DLL或Manifest文件一个个拷贝过去。)
(二)LoadLibrary加载动态库。
LoadLibrary不会主动到系统目录或者当前目录寻找Manifest文件,除非EXE(或DLL)程序被嵌入
Manifest文件。(所以如果用LoadLibrary加载动态库,要记得用MT工具把Manifest文件加载到目标EXE
中,否则系统会报R6034错误,此时是在调用FindActCtxSectionString函数时出了错,用GetLastError
知道出错的原因“The requested lookup key was not found in any active activation context”。)
当然,如果系统已经存在该动态库,则可以找到系统中同名动态库的位置,LoadLibrary该同名动态库。
(如MSVCR80.dll,系统可能已经存在该动态库,此时LoadLibrary输入参数应该是系统已经知道的该动态库
的路径,而不是当前路径。)
c、用静态链接的方法可以把动态库直接嵌到目标EXE中,就不会有Manifest文件引发的R6034错误。此时Manifest文件
相当于没用。
d、如果实在解决不了R6034的错误,下下策可以采用以下方法。
把所有你的动态库都用静态链接编译,最终产生一个不会报R6034错误的程序,在一个一个DLL的改为动态链接,如果发现某个
DLL改了以后会导致报R6034错误,那该DLL可能出错。譬如,该DLL在Setting中没设置Generate Manifest为No,
这就会导致问题。