C++ FreeLibrary释放加载的dll时检测到严重错误c0000374
尝试释放用户定义的DLL时遇到内存错误。如果您不想知道这个问题的背景,我建议您从第2节开始阅读我的问题用户定义的DLL 背景 在我的程序中,我需要使用第三方库在下面的部分中,我称之为C++ FreeLibrary释放加载的dll时检测到严重错误c0000374,c++,c,visual-studio,dll,C++,C,Visual Studio,Dll,尝试释放用户定义的DLL时遇到内存错误。如果您不想知道这个问题的背景,我建议您从第2节开始阅读我的问题用户定义的DLL 背景 在我的程序中,我需要使用第三方库在下面的部分中,我称之为LIB-A/DLL-A。该库的抽象过程可以用4个函数来描述: initResources(): initialze the configuration. callAPI_to_saveAsFile(...): main process. freeMem(...): free memory of returned da
LIB-A
/DLL-A
。该库的抽象过程可以用4个函数来描述:
initResources(): initialze the configuration.
callAPI_to_saveAsFile(...): main process.
freeMem(...): free memory of returned data.
destroyResources(): free memory of the configuration.
使用的LIB-A
引用了ice34d.dll
,以及iceutil34d.dll
。通过在我的项目中添加lib和包含的文件(我称这个程序为exe-A
),我发现这些函数可以很好地工作
但是现在我必须使用另一种方法来引用DLL-A
。换句话说,我必须使用LoadLibrary
、GetProcAddress
和FreeLibrary
来完成这项任务。由于我发现DLL-A
不提供上述函数的任何可用接口,因此我尝试从包含exe-A
的文件夹中删除DLL-A
。结果表明,DLL-A
不是一个有效的文件,exe-A
可以在没有它的情况下正常工作
用户定义DLL
由于DLL-A
无效,我必须编写一个用户定义的DLL来包装上述4个函数,我将此程序称为DLL-B
<代码>DLL-B已与此类LIB链接:
iced.lib
iceutild.lib
LIB-A
虽然DLL-A
无效,但是LIB-A
是必要的,因为我推断上述4个基础不仅在LIB-A
中声明,而且在LIB-A
中定义,而且DLL-A
实际上是空的。在设置libs和包含的文件之后,我编写了4个包装函数。下面是.h文件和.cpp文件的主要部分
.h文件:(省略了一些参数)
.cpp文件:
#include "stdafx.h"
#pragma comment (lib, "../music-lib/release_dll/iced.lib")
#pragma comment (lib, "../music-lib/release_dll/iceutild.lib")
#pragma comment (lib, "../music-lib/release_dll/DLLA.lib")
int w_initResources(){
return initResources();
}
int w_destroyResources(){
return destroyResources();
}
int w_freeMem(...){
return freeMem(...);
}
int w_callAPI_to_saveAsFile(...){
return callAPI_to_saveAsFile(...);
}
char* w_callAPI_to_downFileByte(char* fileURL,char *ret_bytes){
return callAPI_to_downFileByte(fileURL, ret_bytes);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
callAPI_to_saveAsFile_ptr Proc_API = NULL;
initResources_ptr init_API = NULL;
destroyResources_ptr destru_API = NULL;
freeMem_ptr free_API = NULL;
HINSTANCE h = LoadLibraryA("DLLB.dll");
cout << "ERROR:" << GetLastError() << endl;
if (h){
Proc_API = (callAPI_to_saveAsFile_ptr)GetProcAddress(h, "w_callAPI_to_saveAsFile");
init_API = (initResources_ptr)GetProcAddress(h, "w_initResources");
destru_API = (destroyResources_ptr)GetProcAddress(h, "w_destroyResources");
free_API = (freeMem_ptr)GetProcAddress(h, "w_freeMem");
cout << "Have loaded: " << "DLLB.dll" << " successfully!" << endl;
}
else{
cout << "Do not find this DLL:" << "DLLB.dll" << endl;
FreeLibrary(h);
return 0x100;
}
int errorflag=0;
if (Proc_API==NULL){
cout << "Function not loaded: callAPI_to_saveAsFile" << endl;
errorflag = errorflag | 0x001;
}
if (init_API==NULL){
cout << "Function not loaded: initResources" << endl;
errorflag = errorflag | 0x002;
}
if (destru_API==NULL){
cout << "Function not loaded: destroyResources" << endl;
errorflag = errorflag | 0x004;
}
if (CMISS_free_API==NULL){
cout << "Function not loaded: freeMem" << endl;
errorflag = errorflag | 0x008;
}
if (errorflag!=0){
FreeLibrary(h);
return 0x100 | errorflag;
}
cout << "Function loaded successfully!" << endl;
...Perform above functions...
if(h)
FreeLibrary(h);
return 0;
问题
毕竟,我开始编写一个测试程序(我称之为exe-B
)。在这个程序中,我使用这些代码加载DLL-B
:
.h文件:
typedef int (*callAPI_to_saveAsFile_ptr)(...);
typedef int (*initResources_ptr)();
typedef int (*destroyResources_ptr)();
typedef int (*freeMem_ptr)(...);
.cpp文件:
#include "stdafx.h"
#pragma comment (lib, "../music-lib/release_dll/iced.lib")
#pragma comment (lib, "../music-lib/release_dll/iceutild.lib")
#pragma comment (lib, "../music-lib/release_dll/DLLA.lib")
int w_initResources(){
return initResources();
}
int w_destroyResources(){
return destroyResources();
}
int w_freeMem(...){
return freeMem(...);
}
int w_callAPI_to_saveAsFile(...){
return callAPI_to_saveAsFile(...);
}
char* w_callAPI_to_downFileByte(char* fileURL,char *ret_bytes){
return callAPI_to_downFileByte(fileURL, ret_bytes);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
callAPI_to_saveAsFile_ptr Proc_API = NULL;
initResources_ptr init_API = NULL;
destroyResources_ptr destru_API = NULL;
freeMem_ptr free_API = NULL;
HINSTANCE h = LoadLibraryA("DLLB.dll");
cout << "ERROR:" << GetLastError() << endl;
if (h){
Proc_API = (callAPI_to_saveAsFile_ptr)GetProcAddress(h, "w_callAPI_to_saveAsFile");
init_API = (initResources_ptr)GetProcAddress(h, "w_initResources");
destru_API = (destroyResources_ptr)GetProcAddress(h, "w_destroyResources");
free_API = (freeMem_ptr)GetProcAddress(h, "w_freeMem");
cout << "Have loaded: " << "DLLB.dll" << " successfully!" << endl;
}
else{
cout << "Do not find this DLL:" << "DLLB.dll" << endl;
FreeLibrary(h);
return 0x100;
}
int errorflag=0;
if (Proc_API==NULL){
cout << "Function not loaded: callAPI_to_saveAsFile" << endl;
errorflag = errorflag | 0x001;
}
if (init_API==NULL){
cout << "Function not loaded: initResources" << endl;
errorflag = errorflag | 0x002;
}
if (destru_API==NULL){
cout << "Function not loaded: destroyResources" << endl;
errorflag = errorflag | 0x004;
}
if (CMISS_free_API==NULL){
cout << "Function not loaded: freeMem" << endl;
errorflag = errorflag | 0x008;
}
if (errorflag!=0){
FreeLibrary(h);
return 0x100 | errorflag;
}
cout << "Function loaded successfully!" << endl;
...Perform above functions...
if(h)
FreeLibrary(h);
return 0;
如果我不释放库,这个程序就不会有错误
为了证明我的猜测,我又做了两个实验:
表1
我写了一个DLL(DLL-C
)来包装我自己设计的另一个库(LIB-D
)。我在节中用类似的方法加载DLL-C
。问题结果表明,DLL-C
可以无错误地释放。DLL-C和DLL-B之间的唯一区别是DLL-B加载第三方库(ice
,LIB-A
),DLL-C加载我自己设计的简单库(LIB-D
)。这个错误似乎是由第三方LIB触发的。不幸的是,我看不到这些外部LIB的细节
Exp2
我将.cpp文件更改如下:
HINSTANCE h = LoadLibraryA("DLLB.dll");
cout << "ERROR:" << GetLastError() << endl;
if (h){
cout << "H_Valid!" << endl;
FreeLibrary(h);
cout << "Have loaded: " << "DLLB.dll" << " successfully and free it!" << endl;
return 0;
}
else{
cout << "Do not find this DLL:" << "DLLB.dll" << endl;
FreeLibrary(h);
return 0x100;
}
我怎样才能解决这个问题?这是否意味着我不能免费使用图书馆,但可以正常使用我建议你先用C做,而不是C++。对于C++我看不到任何理由。这可以消除更复杂的C++编译器/链接器/加载程序的问题。哦,事实上,我已经使用C++,这个问题存在。为了消除C++库的其他影响,我使用一种更简单的形式来测试这个问题。只是因为程序在某个点崩溃(比如卸载共享库)并不意味着bug在哪里。该bug可能存在于代码中的任何位置,它在以前某个点执行,最终损坏了内部内存堆,但没有崩溃,执行一直持续到此时,一个相当破坏性的操作(卸载共享库)遇到损坏的内存并崩溃。您的bug可以出现在代码中的任何地方。欢迎阅读C++。为了便于阅读和理解:1)通过一个空行单独的代码块(对于,如果,否则,do…,同时,切换,CASE,默认)。2) 一致地缩进代码。在每个左大括号“{”之后缩进。在每个右大括号“}”之前取消缩进。建议为每个缩进级别使用4个空格。在这一行之后:
HINSTANCE h=LoadLibraryA(“DLLB.dll”)代码>,发布的代码调用<代码> cOut.我建议您先用C来做,而不是C++。对于C++我看不到任何理由。这可以消除更复杂的C++编译器/链接器/加载程序的问题。哦,事实上,我已经使用C++,这个问题存在。为了消除C++库的其他影响,我使用一种更简单的形式来测试这个问题。只是因为程序在某个点崩溃(比如卸载共享库)并不意味着bug在哪里。该bug可能存在于代码中的任何位置,它在以前某个点执行,最终损坏了内部内存堆,但没有崩溃,执行一直持续到此时,一个相当破坏性的操作(卸载共享库)遇到损坏的内存并崩溃。您的bug可以出现在代码中的任何地方。欢迎阅读C++。为了便于阅读和理解:1)通过一个空行单独的代码块(对于,如果,否则,do…,同时,切换,CASE,默认)。2) 一致地缩进代码。在每个左大括号“{”之后缩进。在每个右大括号“}”之前取消缩进。建议为每个缩进级别使用4个空格。在这一行之后:HINSTANCE h=LoadLibraryA(“DLLB.dll”)代码>,发布的代码调用cout
Critical error detected c0000374
exeB.exe has triggered a breakpoint.