Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Windows上放置不安全DLL清理代码的安全位置?_Windows_Visual C++_Dll_Loadlibrary_Dllmain - Fatal编程技术网

在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)。人们甚至可以将其用于一般用途: