linux一个进程只有一个堆,不要考虑这些问题,但是windows一个进程可能有多个堆,要在对应的堆上释放。
一, MT改MD
一个进程的地址空间是由一个可执行模块和多个DLL模块构成的,这些模块中,有些可能会链接到C/C++运行库的静态版本,有些可能会链接到C/C++运行库的DLL版本。当使用运行库的DLL版本时,由于dll加载到进程中只会在地址空间中存有一份,因此共用的是同一个堆。所以将可执行模块和DLL模块统一修改为MD编译,则可以直接实现跨模块之间的内存申请和释放,而不会存在任何问题。
二, DLL提供释放接口
每个模块自己封装好释放对应内存的接口,分配资源的接口和释放资源的接口成对封装吧,然后外部模块调用就好了。
三, 使用主进程堆申请和释放内存
如果非要A模块申请的内存,B模块来释放,并且A模块还没有对应的接口,那就大家都使用一个堆就好了,申请和释放都用GetProcessHeap()指定好使用主进程堆。
DLL:
```cpp
void* __stdcall Test(int *len)
{
void* pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
if (pData == NULL)
return NULL;
//使用的是HEAP_ZERO_MEMORY,会自动把内存块的内容都清零
//下面这行代码可以不要的
memset(pData, 0, 100);
char pBuf[] = "十点十分十分十分";
memcpy(pData, pBuf, sizeof(pBuf));
*len = 100;
return pData;
}
可执行程序:
int main()
{
HMODULE hLib = LoadLibraryA("Dll1.dll");
if (nullptr == hLib)
{
std::cout << "LoadLibraryA fail, error:" << GetLastError() << std::endl;
return 0;
}
Fun fun = (Fun)GetProcAddress(hLib, "Test");
if (nullptr == fun)
{
std::cout << "GetProcAddress fail, error:" << GetLastError() << std::endl;
return 0;
}
int nLen = 0;
char *pData = (char*)fun(&nLen);
std::string strTemp(pData, nLen);
HeapFree(GetProcessHeap(), 0, pData);
std::cout << strTemp << std::endl;
return 0;
}
windows允许一个进程中有多个heap,那么这样就需要指明一块内存要在哪个heap上分配,win32的HeapAlloc函数就是这样设计的,给出一个heap的句柄,给出一个size,然后返回一个指针。每个进程都至少有一个主heap,可以通过GetProcessHeap来获得,其它的堆,可以通过GetProcessHeaps取到。同样,内存释放的时候通过HeapFree来完成,还是需要指定一个堆。