Что делать при сбое вызова FreeLibrary API? - PullRequest
10 голосов
/ 27 мая 2011

Вопрос

У меня есть сторонняя DLL, которая выдает необработанное исключение при попытке выгрузить его из моего родного приложения на Си.Это приводит к сбою FreeLibrary и загрузке модуля в моем процессе.

Есть ли варианты принудительной выгрузки библиотеки?

Что вы делаете, когда FreeLibrary вызывает?

ДополнительноСправочная информация

При использовании динамического связывания во время загрузки это довольно раздражает, но в конечном итоге приложение разрушается ОС.Проблема возникает при использовании динамического связывания во время выполнения.Я загружаю эту DLL, использую ее, а затем в некоторых случаях мне нужно выгрузить ее из виртуального адресного пространства моего процесса, а затем продолжить работу.Когда я вызываю FreeLibrary в сторонней библиотеке, она выполняет некоторую работу по очистке (то есть в DllMain, когда вызывается DLL_PROCESS_DETACH ).В то время как он выполняет очистку, он вызывает исключение, которое он не обрабатывает, и превращается в необработанное исключение для FreeLibrary.В результате происходит сбой вызова и модуль остается загруженным.

Я отправил заявку поставщику, так что, надеюсь, я смогу найти исправление, которое позволит этой конкретной библиотеке успешно выгружаться.Однако, если я этого не сделаю, и для общего случая этой проблемы, мне любопытно, какие есть варианты.

Ответы [ 3 ]

7 голосов
/ 27 мая 2011

Если вы только после выгрузки dll из памяти, вы можете использовать

UnmapViewOfFile

, предоставляя базовый адрес вашей загруженной dll какаргумент.

Пример:

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( ) );
   }
}

Или если это библиотека, которую вы не загружали явно (например, зависимость библиотеки, которая была загружена библиотекой, которую вы загрузили), и вы не 'не иметь дескриптор, затем используйте 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( ) );
   }
}
1 голос
/ 27 января 2012

Вероятно, это не та проблема, с которой вы сталкиваетесь, но в случае, если это:

При использовании поддержки компоновщика для динамического линкования во время выполнения, не забудьте использовать / Delay:Выгрузить аргумент.

1 голос
/ 27 мая 2011

Я думаю, что есть только одно возможное решение - взаимодействовать с dll через выделенный поток.Так что со временем вам нужно выгрузить dll, вы просто выйдете (или можете быть уничтожены), этот поток и все связанные с ним ресурсы будут освобождены.В этом случае вы не гарантированы от утечек памяти, но я предлагаю это решение как временное, пока 3d party не исправит ошибки в dll

...