Ошибка LoaderLock при завершении программы

Недавно я интегрировал компонент ведения журнала.NET NLog в одно из наших приложений, разработанных исключительно в неуправляемом коде (компоненты C++ и VB6, скомпилированные в Visual Studio 6). У нас есть несколько приложений C++, которые общаются с NLog через интерфейс COM.

На данный момент все работает нормально, но я замечаю, что появляется следующее сообщение (в окне вывода при отладке компонента C++ в VS6; как приглашение в IDE при отладке NLog через VS 2005) во время завершения программы:

LoaderLock обнаружен. Сообщение: Попытка управляемого выполнения внутри блокировки загрузчика ОС. Не пытайтесь запускать управляемый код внутри функции инициализации DllMain или изображения, так как это может привести к зависанию приложения.

DllMain выглядит следующим образом:

extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        _Module.Init(ObjectMap, hInstance);
        DisableThreadLibraryCalls(hInstance);
    }
    else if (dwReason == DLL_PROCESS_DETACH)
        _Module.Term();
    return TRUE;    // ok
}

Я думаю, что _Module.Term(); теперь включает в себя освобождение некоторых ссылок.NET (я сохраняю ссылку на объект NLog в одном из моих классов C++, чтобы избежать необходимости создавать экземпляры и выпускать каждый раз), что вызывает появление этого предупреждения.

Мой вопрос: это безопасно игнорировать? Если это не так, что является хорошим решением? (лучшее, что я могу придумать, - это создать ссылку на этот объект NLog и выпускать ее каждый раз, когда я захочу записать в файл журнала... не самое элегантное из решений)

2 ответа

Решение

Совершенно определенно небезопасно игнорировать это сообщение. Если вы нажмете это сообщение, вы почти наверняка создали реальное нарушение политики блокировки загрузчика. Это очень серьезная ошибка, которая может привести к непредсказуемому поведению в программе (включая взаимоблокировку).

Лучший способ избежать этого - не иметь доступа к каким-либо другим объектам / функциям.Net прямо или косвенно внутри main DLL. В вашем случае, вероятно, лучше использовать другую политику кэширования. Возможно, создайте объект с подсчетом ссылок для хранения ссылки.Net. Таким образом, объект будет освобожден до вызова DllMain для выгрузки (DLL не может быть выгружен, пока все ваши объекты не будут уничтожены).

Не игнорируй У меня была проблема LoaderLock при запуске приложения C#, которое использовало неуправляемую C++ DLL. В этом случае часть кода DLL (перенесенного из Linux) имела статические данные, которые обращались к файлам при инициализации во время загрузки. После очистки статики проблема LoaderLock была исправлена. Аналогичным образом, если у вас есть статические C/C++, которые обращаются к файлам во время очистки, это может способствовать вашей LoaderLock.

Другие вопросы по тегам