`
xiaoer_1982
  • 浏览: 1806927 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

xp下用户程序空间分配(7):Heap

阅读更多

快乐虾

http://blog.csdn.net/lights_joy/

lights@hb165.com

本文适用于

Xp sp3

vs2008

欢迎转载,但请保留作者信息

我们都知道在程序里可以使用malloc在堆上分配内存,显然windows应该为这个Heap分配一块空间的,我们在主程序里用malloc分配一小块内存,看看指针指向哪里:

char* p = (char*)malloc(10);

得到一个指针:0x00b267b0

在内存块里面找,很容易就发现了目标:

基址

分配基址

分配保护

大小

状态

保护

类型

00b20000

00b20000

00000004
PAGE_READWRITE

00007000

00001000
MEM_COMMIT

00000004
PAGE_READWRITE

00020000
MEM_PRIVATE

00b27000

00b20000

00000004
PAGE_READWRITE

00009000

00002000
MEM_RESERVE

00000000

00020000
MEM_PRIVATE

从这里可以发现malloc采用的算法并不会在一开始就分配一块很大的内存,如果我们接着用:

p = (char*)malloc(0x10000);

分配一块64K的内存,这时可以发现又多了一块内存:

基址

分配基址

分配保护

大小

状态

保护

类型

00cd0000

00cd0000

00000004
PAGE_READWRITE

00012000

00001000
MEM_COMMIT

00000004
PAGE_READWRITE

00020000
MEM_PRIVATE

00ce2000

00cd0000

00000004
PAGE_READWRITE

000ee000

00002000
MEM_RESERVE

00000000

00020000
MEM_PRIVATE

而这块内存在第一次分配时是空闲的。

由此可以猜测,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内存。

1 参考资料

xp下用户程序空间分配(6):加载用户DLL(2009-8-28)

xp下用户程序空间分配(5):加载系统DLL(2009-8-27)

xp下用户程序空间分配(4):加载主程序(2009-8-27)

xp下用户程序空间分配(3):加载文件(2009-8-26)

xp下用户程序空间分配(2):栈(2009-8-26)

xp下用户程序空间分配(1):大致框架(2009-8-26)

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics