当前位置:主页   - 电脑 - 程序设计 - C/C++
xp下用户程序空间分配(7):Heap
来源:网络   作者:快乐虾   更新时间:2011-08-11
收藏此页】    【字号    】    【打印】    【关闭

  我们都知道在程序里可以使用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要将这c系统DLL尽量往高处放!

  趁热打铁,咱创建一个最简单的console application,这样就没有太多的DLL来进行干扰。再运行上面的代码,这样可以得到一个最大的内存块大小0x6c4d d000,期望能够直接分配,但是--------失败了!

  考虑windows的内存块分配是以0x10000进行对齐的,尝试分配0x6c4d0000,这回可算成功了,哈哈,咱就有了1.8G的空间!但是malloc函数的执行过程超慢,过了足足十几秒才分配成功,不知道它到底还要做些什么工作。而且其它程序的运行就此变成蜗牛速度,呵呵。

  顺带说一下,俺只有2G内存。

编缉推荐阅读以下文章

  • xp下用户程序空间分配(9):还剩下什么?
  • xp下用户程序空间分配(8):MEM_MAPPED
  • xp下用户程序空间分配(6):加载用户DLL
  • xp下用户程序空间分配(5):加载系统DLL
  • xp下用户程序空间分配(4):加载主程序
  • xp下用户程序空间分配(3):加载文件
  • xp下用户程序空间分配(2):栈
  • xp下用户程序空间分配(1):大致框架
其它资源
来源声明

版权与免责声明
1、本站所发布的文章仅供技术交流参考,本站不主张将其做为决策的依据,浏览者可自愿选择采信与否,本站不对因采信这些信息所产生的任何问题负责。
2、本站部分文章来源于网络,其版权为原权利人所有。由于来源之故,有的文章未能获得作者姓名,署“未知”或“佚名”。对于这些文章,有知悉作者姓名的请告知本站,以便及时署名。如果作者要求删除,我们将予以删除。除此之外本站不再承担其它责任。
3、本站部分文章来源于本站原创,本站拥有所有权利。
4、如对本站发布的信息有异议,请联系我们,经本站确认后,将在三个工作日内做出修改或删除处理。
请参阅权责声明