加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

从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 *,调用者不应该拥有该指针的所有权.想必.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读