Ошибка LoaderLock при завершении программы - PullRequest
2 голосов
/ 29 января 2009

Недавно я интегрировал компонент ведения журнала .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 ]

6 голосов
/ 29 января 2009

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

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

2 голосов
/ 29 января 2009

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

...