从DllMain调用LoadLibrary
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从DllMain调用LoadLibrary相关的知识,希望对你有一定的参考价值。
它不能调用LoadLibrary或LoadLibraryEx函数(或调用这些函数的函数),因为这可能会在DLL加载顺序中创建依赖循环。这可能导致在系统执行其初始化代码之前使用DLL。
我试图从DllMain打电话给LoadLibrary
但没有任何反应。
我看到的唯一问题是加载的DLL将在我的DllMain执行的其余部分之前使用我的DLL中的函数。
为什么我不能在DllMain中调用LoadLibrary?
编辑:
好吧,我意识到我不能在DllMain中调用LoadLibrary只是因为我必须像其他信徒一样相信MSDN(我在那里看到了一些错误的东西,但我也应该忘记它们)。 并且因为在较新版本的Windows中可能会发生某些事情(尽管过去十年没有任何变化)。
但是,任何人都可以显示一个代码,它将重现在DllMain中调用LoadLibrary
时会发生什么的错误吗?在任何现有的Windows操作系统?
不只是在另一个内部调用一个单例初始化函数,而在DllMain中调用LoadLibrary
?
你赞成继续这样做的论点似乎是:
微软表示不这样做,但我的单个测试案例似乎有效,因此我不明白为什么没有人应该这样做。
你在一个很大的假设下运行:你假设Windows加载器的底层实现永远不会改变。如果在“Windows 8”中更改加载程序以使您的代码无法正常工作,该怎么办?现在微软因此受到指责,他们必须包含另一个兼容性黑客来解决他们告诉你不要写的代码。
遵循指南。他们并不只是为了让你的生活更加艰难,他们在那里保证你的代码在未来的Windows上和现在一样好用。
有简单的,甚至不那么简单的情况,从DllMain调用LoadLibrary非常安全。但设计是DllMain被信任不会更改已加载模块的列表。
尽管拥有加载程序锁确实限制了DllMain中可以执行的操作,但它只与LoadLibrary规则间接相关。加载程序锁定的相关目的是序列化访问已加载模块的列表。虽然NTDLL在一个线程中在此列表上工作,但拥有加载程序锁可确保列表不会被在另一个线程中执行的NTDLL代码更改。但是,装载机锁是一个关键部分。它不会阻止同一线程重新获取加载程序锁并更改列表。
如果NTDLL在列表上工作时完全保留自己,这无关紧要。但是,NTDLL规定在此工作中涉及其他代码,如初始化新加载的DLL时。每次NTDLL在列表上工作时都会调用外部,可以选择进行设计。从广义上讲,有两种选择。一种是稳定列表并释放加载程序锁,调用外部,然后获取加载程序锁并恢复列表上的工作,就像从头开始一样,因为外部调用可能已经改变了它。另一种方法是保持加载器锁定并信任被调用的代码,不要做任何改变列表的事情。因此,LoadLibrary在DllMain中成为禁区。
并不是加载器锁做任何事情来阻止DllMain调用LoadLibrary,甚至加载器锁本身使得这样的调用不安全。相反,通过保留加载程序锁,NTDLL信任DllMain不要调用LoadLibrary。
相反,请考虑关于不等待同步对象的DllMain规则。在这里,装载机锁具有直接作用,使其不安全。等待DllMain中的同步对象设置了死锁的可能性。所需要的只是另一个线程已经拥有你正在等待的对象,然后这个另一个线程调用任何等待加载器锁定的函数(例如,LoadLibrary,还有像看似无害的GetModuleHandle这样的函数)。
想要延长或打破DllMain规则可能是恶作剧甚至是彻头彻尾的愚蠢。但是,我必须指出,对于那些质疑这些规则有多么强大或有意义的人来说,至少部分归咎于微软。毕竟,有些并不总是被清楚而有力地记录下来,而且当我最后看时,他们仍然没有记录在他们肯定需要的所有情况下。 (我想到的例外是,至少在Visual Studio 2005之前,编写DLL的MFC程序员被告知将他们的初始化代码放在CWinApp :: InitInstance中,但没有被告知此代码受DllMain规则约束。)
此外,对于任何来自微软的人来说,好像DllMain规则应该被毫无疑问地遵循,这样做会有点富裕。微软自己的程序员违反规则,并且在违反规则后继续存在导致严重的现实问题的例子。
如http://msdn.microsoft.com/en-us/library/ms682583%28VS.85%29.aspx所述:
DllMain中的线程保持加载程序锁定,因此不能动态加载或初始化其他DLL。
干杯
我正在研究一个可能需要在DllMain中使用LoadLibrary的案例,所以在调查时发现了这个讨论。从我今天的经验来看这个更新
读这个可以得到真正可怕的http://blogs.msdn.com/b/oleglv/archive/2003/10/28/56142.aspx。不仅各种锁都很重要,而且libs传递给链接器的顺序也很重要。案件就是说一个bi
现在,我已经在win7下用vc9尝试了这个。是的,它也是。根据libs如何传递给链接器的顺序,使用LoadLibrary工作与否。但是,与win8下的vc11相同,无论链接顺序如何都能正常工作。 Application Verifier不会责怪这一点。
我现在并没有打算以这种方式使用它:)但仅仅是FYI,如果它与win10相同而且更进一步 - 这可能会有更多用处。无论如何,似乎win8下的加载器机制经历了一些明显的变化。
谢谢。
现在已经很晚了,
如果在线程1(T1)上你DllMain加载其他库,那么将调用其他lib的DllMain;这本身就可以,但是说他们的DLLMain创建一个线程(T2)并等待一个事件让T2完成。
现在,如果T2在其处理中加载库,则加载器将无法获取锁,因为T1已经获取了它。当T2挂在LoaderLock上时,它永远不会发出T1等待事件的信号。
这将导致死锁。
可能会有更多这样的场景,我想这里的广泛推理是我们无法确定将在其他库中运行什么代码,所以这是一个好主意(转为最佳实践),不这样做。
以上是关于从DllMain调用LoadLibrary的主要内容,如果未能解决你的问题,请参考以下文章