我們都知道在程序裡可以使用malloc在堆上分配內存,顯然windows應該為這個Heap分配一塊空間的 ,我們在主程序裡用malloc分配一小塊內存,看看指針指向哪裡:
char* p = (char*)malloc (10);
得到一個指針:0x00b267b0
在內存塊裡面找,很容易就發現了目標:
從這裡可以發現malloc采用的算法並不會在一開始就分配一塊很大的內存,如果我們接著用:
p = (char*)malloc(0x10000);
分配一塊64K的內存,這時可以發現又多了一塊內存:
而這塊內存在第一次分配時是空閒的。
由此可以猜測,malloc可以分配得到的最大內存塊應該取 決於最大的空閒塊。寫段代碼測試一下:
void block_test()
{
SYSTEM_INFO info;
MEMORY_BASIC_INFORMATION mi;
HANDLE hProcess;
DWORD dwAddr;
MEMORY_BASIC_INFORMATION miBlock[1000];
int nCount = 0, nMaxSize = 0;
char* p = NULL;
hProcess = GetCurrentProcess();
GetSystemInfo(&info);
dwAddr = (DWORD)info.lpMinimumApplicationAddress;
do
{
VirtualQueryEx(hProcess, (LPCVOID)dwAddr, &mi, sizeof(mi));
memcpy(&miBlock[nCount++], &mi, sizeof(mi));
dwAddr += mi.RegionSize;
if((mi.State & MEM_FREE) && mi.RegionSize > nMaxSize)
nMaxSize = mi.RegionSize;
} while(dwAddr < (DWORD)info.lpMaximumApplicationAddress);
p = malloc(nMaxSize);
………..
}
得到的nMaxSize = 0x34c1 0000,但是內存分配失敗,麼回事?跟蹤一下malloc的執行過程 ,發現在執行過程中有這樣的調整:
blockSize = sizeof(_CrtMemBlockHeader) + nSize + nNoMansLandSize;
經過這樣的調整,blockSize就變成了0x34c1 0024,所以分配失敗。
我們將這 個大小略作調整:
p = malloc(nMaxSize – 0x24);
還是分配失敗。
想想,如果windows 要將一個空閒塊用作heap,那麼想必需要寫入一些輔助信息,咱再把這個大小調小一點:
p = malloc(nMaxSize – 0x124);
哈哈,終於成功了!咱終於分配了885M的內存。
難怪windows 要將這些系統DLL盡量往高處放!
趁熱打鐵,咱創建一個最簡單的console application,這樣就沒有 太多的DLL來進行干擾。再運行上面的代碼,這樣可以得到一個最大的內存塊大小0x6c4d d000,期望能 夠直接分配,但是--------失敗了!
考慮windows的內存塊分配是以0x10000進行對齊的,嘗試分配 0x6c4d0000,這回可算成功了,哈哈,咱就有了1.8G的空間!但是malloc函數的執行過程超慢,過了足 足十幾秒才分配成功,不知道它到底還要做些什麼工作。而且其它程序的運行就此變成蝸牛速度,呵呵 。
順帶說一下,俺只有2G內存。