在Windows上放置不安全DLL清理代码的安全位置?
我们遇到了这样一种情况,对我们来说,将调用放入/在Windows上放置不安全DLL清理代码的安全位置?,windows,visual-c++,dll,loadlibrary,dllmain,Windows,Visual C++,Dll,Loadlibrary,Dllmain,我们遇到了这样一种情况,对我们来说,将调用放入/DLL\u PROCESS\u DETACH是最好的解决方案 当然,你: 从DllMain给FreeLibrary打电话是不安全的 用例是我们有这样一种情况: (unknown client dll or exe) links dynamically or statically to -> -> DLL_1, loads dynamically -> DLL_x DLL_1应以透明方式加载DLL_x。到它的客户机代
DLL\u PROCESS\u DETACH
是最好的解决方案
当然,你:
从DllMain给FreeLibrary打电话是不安全的
用例是我们有这样一种情况:
(unknown client dll or exe) links dynamically or statically to ->
-> DLL_1, loads dynamically -> DLL_x
DLL_1应以透明方式加载DLL_x。到它的客户机代码,它应该动态加载DLL_x。现在,可以延迟加载,这样LoadLibrary
调用就不需要驻留在DLL\u 1的DLL\u进程\u ATTACH
部分
但是,一旦客户端完成了DLL_1,当从进程中卸载DLL_1时/之前,它还应该卸载(=FreeLibrary)DLL_x
没有客户端必须调用的显式DLL\u 1/Uninitialize
函数,有没有办法做到这一点?
我要指出:
-
< L> >代码> DLMNEX/COD>,因此也不能使用任何C++全局静态析构函数。
- 在kernel32/ntdll或共享MS-CRT中是否有其他回调机制来实现这一点
- 还有其他模式可以让这个用例工作吗
- 正确的方法是在DLL_1中显式取消初始化函数
但是,如果您不能做到这一点,您可以通过启动一个helper线程来为您卸载来解决这个问题。如果希望安全起见,请在加载DLL_x的同时启动线程,并让它等待事件对象。(不过,出于记录,一般认为从
DllMain
启动线程是安全的,只要您尊重直到DllMain
退出后线程才会启动的事实。)
显然,助手线程的代码不能在DLL_1中。如果你能修改DLL_x,你可以把它放在那里。如果没有,您将需要一个帮助程序DLL。在任何一种情况下,包含帮助线程代码的DLL都可以使用函数安全地自卸载。
从DllMain调用FreeLibrary是不安全的
-需要理解为什么会这样。仅因为这会导致在系统执行其终止代码后使用DLL。-如果您确切地知道您和其他人都不再使用此DLL(在调用freebrary
之后),则从中调用freebrary
是安全和正常的DllMain@RbMm-否。不安全,因为有文件证明不安全。加载程序不支持它。我承认在相当多的情况下它可能会起作用,但在某些情况下它仍可能爆炸。您的LoadLibrary
示例。这里的问题不在LoadLibrary
调用中,而是在刚刚加载的DLL的调用函数中LoadLibrary
不保证(在加载程序路径中调用recursive时)在LoadLibrary
返回之前调用DLL入口点。这是所有错误的来源-请在初始化DLL之前使用它。但freebrary
的情况并不简单。直到最后一次freebrary
才调用DLL取消初始化。如果您有加载DLL的句柄-您可以100%保证在您自己调用freebrary
explicit之前不会调用它的未初始化代码。即使您从加载程序路径(DllMain
)调用freebrary
),我们可以确保DLL\u X
尚未(也不能)处于卸载过程中,因为它保留了你的参考资料。因此,在调用freebrary
之前,先调用dll中的任何函数,因为此dll是安全的。而且我不认为调用freellibrary
,即使是从DllMain
调用也会造成问题。若你们能举一个这样的例子,你们会很感兴趣的。@RbMm-我不怀疑它在实践中经常有效。我只想引用一句话:“并不是装载机锁做了任何事情来阻止DllMain调用LoadLibrary,甚至不是装载机锁本身使这样的调用不安全。相反,通过保留加载程序锁,NTDLL信任DllMain不调用LoadLibrary。“”整洁。所以我可以写一个助手Dll,然后从助手线程加载Dll_x,然后等待信号。DLL_1随后可以从其DllMain
(因为这是允许的)向帮助程序DLL发送信号,帮助程序DLL中的帮助程序线程将自行终止(如果它是最后一个帮助程序线程,则计数降至零,并卸载帮助程序DLL)。人们甚至可以将其用于一般用途: