MSDN说:
它不能调用LoadLibrary或LoadLibraryEx函数(或调用这些函数的函数),因为这可能会在DLL加载顺序中创build依赖关系循环。 这可能会导致在系统执行初始化代码之前使用DLL。
我试图从DllMain调用LoadLibrary
并没有发生任何事情。
我看到的唯一问题是,在我的DllMain执行之前,加载的DLL将在我的DLL中使用函数。
为什么我不能在DllMain中调用LoadLibrary?
好吧,我意识到,我不能仅仅因为我必须相信其他信徒所做的MSDN(我在那里看到一些错误的东西,但我也应该忘记它们),所以我不能在DllMain中调用LoadLibrary。
而且因为在Windows的新版本中可能会发生一些事情(虽然过去十年没有任何改变)。
但是,任何人都可以显示一个代码,将重现一些不好的事情,当在DllMain中调用LoadLibrary
时会发生什么? 在任何现有的Windows操作系统?
不只是在另一个单独的初始化函数调用,但LoadLibrary
在DllMain?
有很简单的,甚至不是那么简单的情况下,从DllMain调用LoadLibrary是完全安全的。 但设计是,DllMain是值得信赖的不要改变加载模块的列表。
虽然拥有加载器锁确实限制了在DllMain中可以完成的工作,但它仅与LoadLibrary规则间接相关。 加载程序锁定的相关目的是串行访问加载的模块列表。 虽然NTDLL在一个线程中工作在这个列表中,但是拥有加载器锁可以确保列表不会被在另一个线程中执行的NTDLL代码所改变。 然而,装载机锁是一个关键部分。 它不会阻止同一线程重新获取加载程序锁定并更改列表。
如果NTDLL在清单上工作的时候完全保留自己的话,这并不重要。 但是,在初始化一个新加载的DLL时,NTDLL提供了涉及其他代码的工作。 每次NTDLL在列表中工作时都会自行调用,因此可以选择设计。 一般来说,有两种选择。 一个是稳定列表并释放加载程序锁,向外调用,然后获取加载程序锁,并从头重新开始工作,因为外部调用可能已经改变了它。 另一个是保持加载器锁定和信任被调用的代码不做任何改变列表。 因此,LoadLibrary在DllMain中变得不受限制。
这并不是说加载程序锁定会阻止 DllMain调用LoadLibrary,或者甚至加载程序锁定本身使这样的调用不安全。 相反,通过保留加载器锁,NTDLL 相信 DllMain不会调用LoadLibrary。
相比之下,请考虑关于不等待同步对象的DllMain规则。 在这里,装载机锁有直接的作用,使这个不安全。 在DllMain中等待同步对象会造成死锁的可能性。 所需要的就是另一个线程已经拥有了你正在等待的对象,然后这个其他线程调用了任何等待加载器锁的函数(例如,LoadLibrary,而且看起来无害的GetmoduleeHandle)。
想要延长或打破DllMain规则可能是淘气或甚至是愚蠢的。 但是,我必须指出,微软至少在一定程度上要责怪人们询问这些规则有多强或有意义。 毕竟,有些文件并不总是清晰而强有力地记录下来,而当我最后看到的时候,它们在所有确实需要的情况下都还没有记录。 (我记住的例外是,至少在Visual Studio 2005之前,编写DLL的MFC程序员被告知把它们的初始化代码放在CWinApp :: InitInstance中,但是没有被告知这个代码受到DllMain规则的限制。)
而且,对于任何来自微软的人来说,如果遵循DllMain规则,毫无疑问,这应该是有点丰富的。 例如,微软自己的程序员违反了规则,甚至在违反规则之后仍然会导致严重的现实世界的麻烦。
你赞成继续这样做的论点似乎是这样的:
微软说,不要这样做,但我的单一测试案例似乎工作,所以我不明白为什么没有人应该这样做。
你正在经营一个大的假设:你假设Windows加载器的底层实现将永远不会改变。 如果加载程序在“Windows 8”中更改,导致您的代码不能正常工作,该怎么办? 现在微软被指责了,他们必须包括另一个兼容性破解,以解决代码,他们告诉你 不要写在第一位。
遵循指导原则。 他们不是为了让你的生活变得更加困难,而是为了保证你的代码能够像现在一样在未来的Windows上工作。
如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 。 不仅各种锁都很重要,而且也是将库传递给链接器的顺序。 这种情况是说一个双
现在,我已经在win7下用vc9试过了。 是的,也是这样。 取决于库如何传递给链接器的顺序,使用LoadLibrary是否起作用。 但是,与win8下的vc11一样,可以正常工作而不考虑链接顺序。 应用程序验证程序不会对此负责。
我没有打电话现在和到处使用这种方式:)但只是供参考,如果这是相同的win10和进一步 – 这可能会有更多的用处。 无论如何,win8下的加载机制似乎发生了一些明显的变化。
谢谢。