Вопрос вдохновлен этой дискуссией .
Похоже, что опасения, связанные с вызовами C ++ во время выполнения из DllMain (или из глобальных переменных ctor's), несколько устарели. Я часто использую глобальные инициализаторы в dll без каких-либо сбоев, и теперь я запускаю специальную тестовую программу (скомпилированную с VC2010 Express без SP), содержащую exe-модуль со статической связью во время выполнения и dll с динамической. Dll загружается вручную из exe с помощью LoadLibrary ().
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
Нет сбоев, нулевых указателей, ошибок страниц и т. Д.
Профилирование с помощью DependencyWalker также подтверждает, что библиотека времени выполнения (MSVCR100.DLL) загружается только после вызова LoadLibrary (и не предварительно загружается и инициализируется exe).
Кажется, что динамическая библиотека времени выполнения загружается и правильно инициализируется во время процесса загрузки dll_example.dll перед фазой глобальной инициализации.
есть мысли?
PS. Я не рекомендую переводить какой-либо тяжелый код инициализации на глобальную фазу инициализации; но я полагаю, что простой код выделения памяти достаточно безопасен (?).