问:如果我DllMain()在共享库中编写了一个函数,并且还编写了一个带有 的函数__attribute__((constructor)),那么在加载库时会先执行哪个函数?
问:如果我__attribute__((constructor))在链接到该共享库的可执行文件中有函数,首先将调用什么 - 库DllMain()或可执行文件的__attribute__((constructor))函数?
问:如果我DllMain()在共享库中编写了一个函数,并且还编写了一个带有 的函数__attribute__((constructor)),那么在加载库时会先执行哪个函数?
问:如果我__attribute__((constructor))在链接到该共享库的可执行文件中有函数,首先将调用什么 - 库DllMain()或可执行文件的__attribute__((constructor))函数?
A : 函数按以下顺序调用:
DLL constructorDLL DllMain() (process attach)EXE constructorEXE main()EXE main() endsEXE destructorDLL DllMain() (process detach)DLL destructor如果在运行时 ( LoadLibrary()/ FreeLibrary()) 完成链接,则按以下顺序调用函数:
EXE constructorEXE main()EXE LoadLibrary()DLL constructorDLL DllMain() (process attach)EXE main() continuesEXE FreeLibaray()DLL DllMain() (process detach)DLL destructorEXE main() endsEXE destructor如果您忘记释放库,则顺序如下:
EXE constructorEXE main()EXE LoadLibrary()DLL constructorDLL DllMain() (process attach)EXE main() continuesEXE main() endsEXE destructorEXE 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 之后调用。
为什么?