windows FreeLibrary API 调用失败时怎么办?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6153401/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:56:45  来源:igfitidea点击:

What to do when FreeLibrary API call fails?

cwindowswinapidllnative

提问by Zach Burlingame

Question

I have a third-party DLL that throws an unhandled exception when attempting to unload it from my native C application. This results in the call to FreeLibraryfailing, and the module remaining loaded in my process.

我有一个第三方 DLL,它在尝试从我的本机 C 应用程序卸载它时抛出一个未处理的异常。这导致对FreeLibrary的调用失败,并且模块在我的进程中保持加载状态。

Are there any options to forceably unload the library?

是否有任何选项可以强制卸载库?

What do you do when the FreeLibrary calls?

当 FreeLibrary 调用时你会怎么做?

Additional Background

附加背景

When using load-time dynamic linking this is annoying enough, but ultimately the application gets torn down by the OS. The problem comes when using run-time dynamic linking. I load up this DLL, use it, and then in some instances I need to unload it from my process's virtual address space and then continue running. When I call FreeLibrary on the third-party library, it does some cleanup work (i.e. in DllMain when DLL_PROCESS_DETACHis called). While it's doing it's cleanup, it causes an exception to be thrown which it doesn't handle, and bubbles up as an unhandled exception to FreeLibrary. This results in the call failing and the module remaining loaded.

当使用加载时动态链接时,这很烦人,但最终应用程序会被操作系统拆除。使用运行时动态链接时会出现问题。我加载这个 DLL,使用它,然后在某些情况下我需要从我的进程的虚拟地址空间卸载它,然后继续运行。当我在第三方库上调用 FreeLibrary 时,它会做一些清理工作(即在调用 DLL_PROCESS_DETACH 时DllMain 中)。当它进行清理时,它会导致抛出一个它不处理的异常,并作为一个未处理的异常冒泡到 FreeLibrary。这会导致调用失败并且模块保持加载状态。

I've put a ticket in with the vendor so hopefully I can get a fix which will allow this specific library to unload successfully. In case I don't however, and for the general case of this issue, I'm curious as to what the options are.

我已经向供应商发出了一张票,所以希望我能得到一个修复,这将允许这个特定的库成功卸载。但是,如果我不这样做,对于这个问题的一般情况,我很好奇有哪些选项。

采纳答案by crypted

If you are after only unloading dll from the memory you can use

如果您只是从内存中卸载 dll 之后,您可以使用

UnmapViewOfFile

取消映射文件视图

providing bases address of your loaded dll as an argument.

提供加载的 dll 的基地址作为参数。

Example:

例子:

HINSTANCE hInst = LoadLibrary( "path_to_dll" );

if( !FreeLibrary( hInst ) )
{
   fprintf( stderr, "Couldn't unload library. Error Code: %02X\n. Attempting to unmap...", GetLastError() );
   if( !UnmapViewOfFile( hInst ) )
   { 
     fprintf( stderr, "Couldn't unmap the file! Error Code: %02X\n", GetLastError( ) );
   }
}

Or if it's a library that you didn't explicitly load (e.g. a library dependency that was loaded by a library that you loaded) and you don't have the handle, then use GetModuleHandle:

或者,如果它是您未显式加载的库(例如,由您加载的库加载的库依赖项)并且您没有句柄,则使用GetModuleHandle

HINSTANCE hInst = GetModuleHandle( "dllname_you_didn't_load" );
if( hInst != NULL )
{
   if( !UnmapViewOfFile( hInst ) )
   { 
     fprintf( stderr, "Couldn't unmap the file! Error Code: %02X\n", GetLastError( ) );
   }
}

回答by Anton Semenov

I think there is only one possible solution - interop with dll through dedicated thread. So in time you need to unload dll you just exit (or may be kill) that thread and all associated with it resources will be freed. In this case you are not guaranteed about memory leaks, but I suggest this solution as temporary, till 3d party fixes bugs in dll

我认为只有一种可能的解决方案 - 通过专用线程与 dll 互操作。因此,及时您需要卸载 dll,您只需退出(或可能被杀死)该线程,并且所有与之相关的资源都将被释放。在这种情况下,您不能保证内存泄漏,但我建议将此解决方案作为临时解决方案,直到 3d 方修复 dll 中的错误

回答by user541686

This is probably not the issue you're experience, but in case it is:

这可能不是您遇到的问题,但如果是:

When using linker support for run-time dynamic linking, don't forget to use the /Delay:Unloadargument.

使用链接器支持运行时动态链接时,不要忘记使用/Delay:Unload参数。