问:如果我DllMain()
在共享库中编写了一个函数,并且还编写了一个带有 的函数__attribute__((constructor))
,那么在加载库时会先执行哪个函数?
问:如果我__attribute__((constructor))
在链接到该共享库的可执行文件中有函数,首先将调用什么 - 库DllMain()
或可执行文件的__attribute__((constructor))
函数?
问:如果我DllMain()
在共享库中编写了一个函数,并且还编写了一个带有 的函数__attribute__((constructor))
,那么在加载库时会先执行哪个函数?
问:如果我__attribute__((constructor))
在链接到该共享库的可执行文件中有函数,首先将调用什么 - 库DllMain()
或可执行文件的__attribute__((constructor))
函数?
A : 函数按以下顺序调用:
DLL constructor
DLL DllMain() (process attach)
EXE constructor
EXE main()
EXE main() ends
EXE destructor
DLL DllMain() (process detach)
DLL destructor
如果在运行时 ( LoadLibrary()
/ FreeLibrary()
) 完成链接,则按以下顺序调用函数:
EXE constructor
EXE main()
EXE LoadLibrary()
DLL constructor
DLL DllMain() (process attach)
EXE main() continues
EXE FreeLibaray()
DLL DllMain() (process detach)
DLL destructor
EXE main() ends
EXE destructor
如果您忘记释放库,则顺序如下:
EXE constructor
EXE main()
EXE LoadLibrary()
DLL constructor
DLL DllMain() (process attach)
EXE main() continues
EXE main() ends
EXE destructor
EXE FreeLibaray() (system cleans up for you)
DLL DllMain() (process detach)
DLL destructor
考虑代码
EXE文件:
int main ()
{
printf("Executable Main, loading library\n");
#ifdef HAVE_WINDOWS
HMODULE lib = LoadLibraryA ("testdll.dll");
#elif defined(HAVE_LINUX)
void * lib = dlopen("testdll.so", RTLD_LAZY);
#endif
if (lib) {
printf("Executable Main, Freeing library\n");
#ifdef HAVE_WINDOWS
FreeLibrary (lib);
#elif defined(HAVE_LINUX)
dlclose(lib);
#endif
}
printf("Executable Main, exiting\n");
return 0;
}
动态链接库
struct Moo
{
Moo() { printf("DLL Moo, constructor\n"); }
~Moo() { printf("DLL Moo, destructor\n"); }
};
Moo m;
#ifdef HAVE_WINDOWS
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
printf("DllMain, DLL_PROCESS_ATTACH\n");
break;
case DLL_THREAD_ATTACH:
printf("DllMain, DLL_THREAD_ATTACH\n");
break;
case DLL_THREAD_DETACH:
printf("DllMain, DLL_THREAD_DETACH\n");
break;
case DLL_PROCESS_DETACH:
printf("DllMain, DLL_PROCESS_DETACH\n");
break;
default:
printf("DllMain, ????\n");
break;
}
return TRUE;
}
#else
CP_BEGIN_EXTERN_C
__attribute__((constructor))
/**
* initializer of the dylib.
*/
static void Initializer(int argc, char** argv, char** envp)
{
printf("DllInitializer\n");
}
__attribute__((destructor))
/**
* It is called when dylib is being unloaded.
*
*/
static void Finalizer()
{
printf("DllFinalizer\n");
}
CP_END_EXTERN_C
#endif
输出不同: 在 windows Executable Main,加载库 DLL Moo,构造函数 DllMain,DLL_PROCESS_ATTACH Executable Main,释放库 DllMain,DLL_PROCESS_DETACH DLL Moo,析构函数 Executable Main,退出
Linux Executable Main,加载库 DllInitializer DLL Moo,构造函数 Executable Main,释放库 DllFinalizer DLL Moo,析构函数 Executable Main,退出
在 Windows 上,Moo 构造函数在 DLLMain 之前调用,而在 linux 上,它在使用属性((constructor)) 定义的 Initializer 之后调用。
为什么?