从DllMain或全局初始化程序调用c运行时
发布时间:2020-12-16 09:32:56 所属栏目:百科 来源:网络整理
导读:问题的灵感来自 this discussion. 似乎有关DllMain(或来自全局变量ctor)的C运行时调用的担忧已经过时了.我经常在dll中使用全局初始化器而没有任何错误,现在我运行了一个特殊的测试程序(用VC2010 Express w / o SP编译),其中包含带有静态运行时链接的exe模块
问题的灵感来自
this discussion.
似乎有关DllMain(或来自全局变量ctor)的C运行时调用的担忧已经过时了.我经常在dll中使用全局初始化器而没有任何错误,现在我运行了一个特殊的测试程序(用VC2010 Express w / o SP编译),其中包含带有静态运行时链接的exe模块和带有动态链接的dll. Dll是由LoadLibrary()从exe加载的. Dll在全局初始化期间创建并填充地图对象(因此使用运行时库,至少是内存分配函数). Dll代码: #include <map> using namespace std; struct A{ char* p; static const int num=1000; map<int,string> m; A(){ for(int i=0; i<num; ++i){m[i]= *new string("some text");} } }; A a; extern "C"{ _declspec(dllexport) const char* getText(int i){ return a.m[i].data(); } } exe代码(用于发布配置;将运行时库名称更改为MSVCR100D.DLL以进行调试): #include <windows.h> typedef const char* (*pfunc_t)(int idx); int main(int argc,TCHAR* argv[]) { HMODULE h_crt= GetModuleHandle("MSVCR100.DLL"); // ensure that runtime library is NOT loaded yet: MessageBox(NULL,(NULL==h_crt)? "CRT NOT loaded by .exe module": "CRT Loaded by .exe module","before LoadLibrary",MB_OK); HMODULE hlib=LoadLibrary("dll_example.dll"); h_crt= GetModuleHandle("MSVCR100.DLL"); MessageBox(NULL,(NULL==h_crt)? "CRT NOT loaded": "CRT Loaded","after LoadLibrary",MB_OK); pfunc_t pfunc= (pfunc_t)(void*)GetProcAddress(hlib,"getText"); MessageBox(NULL,pfunc(99),"map[99]",MB_OK); return 0; } 输出如预期: before LoadLibrary: CRT NOT loaded by .exe module after LoadLibrary: CRT Loaded map[99]: some text 没有失败,nullpointers,pagefaults等. 使用DependencyWalker进行性能分析也确认运行时lib(MSVCR100.DLL)仅在LoadLibrary调用之后加载(并且不由exe预加载和初始化). 在全局初始化阶段之前,似乎在dll_example.dll加载过程中正确加载和初始化动态运行时库. 有什么想法吗? PS.我不鼓励将任何重量级初始化代码移动到全局初始化阶段;但我想简单的内存分配代码足够安全(?). 解决方法
在加载DLL时初始化CRT是一种非常常见的情况,例如,任何COM服务器都会发生这种情况.因此,您可以依赖CRT明确支持该场景,只要您不要求它使用代码来初始化您的变量,而代码又依赖于危险的api调用.初始化托管对象是一种着名的故障模式,在保存加载程序锁定时无法初始化CLR.僵局非常难以诊断,但很容易被发现.这一般都是正确的,你可以毫不费力地发现你遇到了问题.只为它寻找解决方法.
然而,通过使用主程序和使用CRT的不同实例的一个或多个DLL,可能需要付出很多代价.这是测试程序中发生的事情.您必须非常仔细地制作DLL的导出函数,以便不返回任何指针或C对象.你将逃避返回const char *,调用者不应该拥有该指针的所有权.想必. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |