为啥不从入口点函数调用 FreeLibrary?
Posted
技术标签:
【中文标题】为啥不从入口点函数调用 FreeLibrary?【英文标题】:Why not call FreeLibrary from entry point function?为什么不从入口点函数调用 FreeLibrary? 【发布时间】:2010-12-26 13:22:29 【问题描述】:我正在编写一个需要多次动态调用单独的 DLL 的 DLL。我想保持被调用者加载,然后在卸载我的 DLL 时将其卸载。但根据微软的说法,那是bad idea。
入口点函数应该只 执行简单的初始化任务 并且不应调用任何其他 DLL 加载或终止功能。为了 例如,在入口点函数中, 你不应该直接或间接地 调用 LoadLibrary 函数或 LoadLibraryEx 函数。此外, 你不应该调用 FreeLibrary 进程运行时的函数 终止。
这是有问题的代码。有人能解释一下为什么我不应该从我的 DLL 入口点调用 LoadLibrary 和 FreeLibrary 吗?
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
switch (ul_reason_for_call)
case DLL_PROCESS_DETACH :
if (hLogLib != NULL) FreeLibrary(hLogLib);
break;
return TRUE;
【问题讨论】:
你怎么知道DLL还没有被卸载? @Anon:我不知道。事实上,我什至不知道它曾经被加载过。但如果它已加载但尚未卸载,我想卸载它。 听起来您应该静态链接到另一个 DLL,而不是尝试动态加载它。 @Remy,如果可以的话,我会的。 DLL 的路径在编译时不可用。 也许压力在于“您不应该在进程终止时调用 FreeLibrary 函数。”也就是说,当进程终止时不做任何事情,也许目标是尽快退出以节省计算资源。 【参考方案1】:我想我找到了the answer。
入口点函数应该 只执行简单的初始化或 终止任务。它不能调用 LoadLibrary 或 LoadLibraryEx 函数(或调用的函数 这些功能),因为这可能 在 DLL 中创建依赖循环 加载顺序。这可能会导致 DLL 在系统有之前被使用 执行其初始化代码。 同样,入口点函数 不得调用 FreeLibrary 函数 (或调用 FreeLibrary 的函数) 在进程终止期间,因为 这可能会导致使用 DLL 系统执行后 终止代码。
【讨论】:
现在还不清楚,库的代码在被终止和释放后会用到什么?我假设一个人只释放一个之前加载的库......并且终止代码仅在此 FreeLibrary 调用释放对该 DLL 的最后引用时运行。【参考方案2】:您不能从入口点调用 LoadLibrary,因为 DllMain 函数在操作系统加载程序锁内运行,任何重新获取该加载程序锁的尝试(例如,通过调用 LoadLibrary)都会导致死锁。
【讨论】:
但是 FreeLibrary 呢?这会导致什么样的问题?【参考方案3】:不要在 DLLMain 内做任何后果。严重地。调用 FreeLibrary 更糟糕,因为它只会有时死锁,如果碰巧你的 free 将 refcount 减为零并且库实际上已被释放。
【讨论】:
以上是关于为啥不从入口点函数调用 FreeLibrary?的主要内容,如果未能解决你的问题,请参考以下文章
动态载入DLL所需要的三个函数详解(LoadLibrary,GetProcAddress,FreeLibrary)
为啥数组会引起nvlink警告:入口函数的堆栈大小不能静态确定
为啥不从谷歌地图标记上的点击事件中调用 navigator.getCurrentPosition (function (position) )