【问题标题】:DLL unloading itselfDLL 自行卸载
【发布时间】:2010-08-04 21:49:23
【问题描述】:

DLL 中的函数是否可以卸载 DLL?我需要这样做以确保 DLL 未在使用中,然后写入 DLL 的文件。

【问题讨论】:

    标签: dll self-reference


    【解决方案1】:

    据我了解,它可以完成,有时也应该完成(例如,在通过 CreateRemoteThread 和其他方法注入 dll 的情况下)。所以,

    FreeLibraryAndExitThread(hModule, 0)
    

    会做到这一点。

    另一方面,调用

    FreeLibrary(hModule)
    

    不会在这里做 - 来自 MSDN:“如果他们分别调用 FreeLibrary 和 ExitThread,就会存在竞争条件。可以在调用 ExitThread 之前卸载库。” 作为备注,除了从线程函数返回之外,ExitThread 还会做一些记账。

    所有这一切都假设您的 Dll 通过从已加载的 Dll 内部调用 LoadLibrary 来获取 hModule 本身,或者更确切地说,通过从已加载的 Dll 内部调用以下函数来获取 hModule:

    GetModuleHandleEx
    (
        GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
        (LPCTSTR)DllMain,
        &hModule
    )
    

    这会增加 Dll 的引用计数,因此您知道,如果您稍后使用该句柄释放库,并且如果库真的被卸载,那么您拥有对它的最后引用。
    如果您在 DLL_PROCESS_ATTACH 期间跳过增加 Dll 的引用计数并仅从 DllMain 的参数获取 hModule,那么您不应调用 FreeLibraryAndExitThread,因为加载 Dll 的代码仍在使用它,这个模块句柄确实不是你来管理的。

    【讨论】:

      【解决方案2】:

      在 dll 完成工作后使用它:

          CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, &__ImageBase, 0, NULL);
          // terminate if dll run in a separate thread ExitThread(0); 
          // or just return out the dll
      

      而 __ImageBase 是你的 dll 的 PE 头结构:

      EXTERN_C IMAGE_DOS_HEADER __ImageBase;
      

      【讨论】:

      • 这个技巧可能会有所帮助,但从理论上讲,如果调用 CreateThread 的线程在调用 CreateThread 后逗留时间过长,它仍然可能导致竞争条件。请参阅我关于 FreeLibraryAndExitThread 函数的回答。
      【解决方案3】:

      我认为它不会起作用。当代码在不再有效的内存位置运行时,使用外部句柄调用 FreeLibrary(LoadLibrary 会从 DLL 外部的区域调用)。

      即使这是可能的,但它闻起来像是一个糟糕的设计。也许您想制作一些更新程序或类似的东西。多解释一下您期望的结果是什么。从内部卸载 DLL 不是可行的方法。

      【讨论】:

      • 请看我关于 FreeLibraryAndExitThread 函数的回答
      • 如果您的 DLL 中有后台线程,则调用 FreeLibrary 不是最佳选择。最好使用FreeLibraryAndExitThread。这个功能是一块可以杀死2只鸟的石头。
      【解决方案4】:

      如果您询问是否可以从 DLL 本身的代码中安全地卸载/取消映射进程中加载​​的 DLL,答案是否定的 - 没有真正安全的方法来做到这一点。

      这样想:卸载 DLL 是通过使用 FreeLibrary() 减少它的引用计数来完成的。问题当然是一旦 DLL 的引用计数达到零,模块就会被取消映射。这意味着 DLL 中调用 FreeLibrary() 的代码消失了。

      即使您可以这样做,您仍然需要确保没有其他线程执行任何从 DLL 导出的函数。

      【讨论】:

        猜你喜欢
        • 2012-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多