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來完成,還是需要指定一個堆。