C++ FreeLibrary释放加载的dll时检测到严重错误c0000374

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

尝试释放用户定义的DLL时遇到内存错误。如果您不想知道这个问题的背景,我建议您从第2节开始阅读我的问题用户定义的DLL

背景 在我的程序中,我需要使用第三方库在下面的部分中,我称之为
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;
}

我怎样才能解决这个问题?这是否意味着我不能免费使用图书馆,但可以正常使用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.