LoadLibraryA方法在加载/卸载超过1000次后返回错误代码1114 (ERROR_DLL_INIT_FAILED)

1 投票
1 回答
8791 浏览
提问于 2025-04-15 23:49

我在用C++编程,使用的是Visual Studio 2008和Windows XP,现在遇到了一个问题:

我的应用程序是一个可以被Python调用的DLL,它会加载一个外部的DLL,使用里面需要的方法,然后再卸载这个外部的DLL。这个过程本来是正常的,但在运行超过1000次后,"LoadLibraryA"这个方法返回了一个空值。

主要步骤是:

HINSTANCE h = NULL;
h = LoadLibraryA(dllfile.c_str());
DWORD dw = GetLastError(); 

出现的错误是:

ERROR_DLL_INIT_FAILED
1114 (0x45A) A dynamic link library (DLL) initialization routine failed.

这个DLL是通过以下方式卸载的:

FreeLibrary(mDLL);
mDLL = NULL;

其中mDLL是这样定义的:

HINSTANCE mDLL;

我尝试的第一个解决办法是:

只加载一次这个DLL,并在应用程序结束时再卸载它。这样解决了之前的问题,但又引入了一个新问题。

当应用程序结束时,首先执行的是其他DLL的DllMain方法,而不是我应用程序的DllMain方法,这样就导致了错误,因为我的应用程序试图卸载一个已经被自己卸载过的DLL。

错误信息是:“在Python.exe中,0x04a00d07(DllName.DLL)发生未处理的异常:0xC0000005:访问冲突,读取位置0x0000006b”。

欢迎任何建议。谢谢!

祝好。

1 个回答

1

确保加载或卸载的库的初始化代码不会造成内存泄漏。很多库只希望被加载一次,而不会总是正确地清理它们的资源。

比如,在C++文件的顶部可以这样声明和初始化一个变量:

AClass *a = new AClass(1,2,3);

这段代码会在库被自动加载时执行。然而,现在很难释放这个悬挂的实例,因为库并不知道它什么时候以及如何会被卸载。如果遇到这种情况,可以把“AClass *a”换成“AClass a”,或者为这个库写一个自己的DllMain,在DLL_PROCESS_DETACH时释放资源。

如果你无法控制库的代码,那么可以考虑创建一个已加载库的缓存,简单地不卸载它们。很难想象会有无限数量的库来超载这样的缓存。

撰写回答