全面介绍Windows内存管理机制及C++内存分配实例(三):虚拟内存

本文背景:

在编程中,很多WindowsC++的内存函数不知道有什么区别,更别谈有效使用;根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结描述,结合实例来阐明这个机制。

本文目的:

Windows内存管理机制了解清楚,有效的利用C++内存函数管理和使用内存。

本文内容:

本文一共有六节,由于篇幅较多,故按节发表。其他章节请看本人博客的Windows内存管理及C++内存分配实例(一)(二)(四)(五)和(六)。

 

3.      内存管理机制 -- 虚拟内存 (VM)

·        虚拟内存使用场合

虚拟内存最适合用来管理大型对象或数据结构。比如说,电子表格程序,有很多单元格,但是也许大多数的单元格是没有数据的,用不着分配空间。也许,你会想到用动态链表,但是访问又没有数组快。定义二维数组,就会浪费很多空间。

它的优点是同时具有数组的快速和链表的小空间的优点。

 

·        分配虚拟内存

如果你程序需要大块内存,你可以先保留内存,需要的时候再提交物理存储器。在需要的时候再提交才能有效的利用内存。一般来说,如果需要内存大于1M,用虚拟内存比较好。

 

·        保留

用以下Windows 函数保留内存块

VirtualAlloc (PVOID 开始地址,SIZE_T 大小,DWORD 类型,DWORD 保护属性)

一般情况下,你不需要指定开始地址,因为你不知道进程的那段空间是不是已经被占用了;所以你可以用NULL大小是你需要的内存字节;类型MEM_RESERVE(保留)、MEM_RELEASE(释放)和MEM_COMMIT(提交)。保护属性在前面章节有详细介绍,只能用前六种属性。

如果你要保留的是长久不会释放的内存区,就保留在较高的空间区域,这样不会产生碎片。用这个类型标志可以达到:

MEM_RESERVE|MEM_TOP_DOWN

C++程序:保留1G的空间

LPVOID pV=VirtualAlloc(NULL,1000*1024*1024,MEM_RESERVE|MEM_TOP_DOWN,PAGE_READWRITE); 

            if(pV==NULL)

            cout<<"没有那么多虚拟空间!"<<endl;

            MEMORYSTATUS memStatusVirtual1;

            GlobalMemoryStatus(&memStatusVirtual1);

            cout<<"虚拟内存分配:"<<endl;

            printf("指针地址=%x/n",pV);

cout<<"减少物理内存="<<memStatusVirtual.dwAvailPhys-memStatusVirtual1.dwAvailPhys<<endl;

cout<<"减少可用页文件="<<memStatusVirtual.dwAvailPageFile-memStatusVirtual1.dwAvailPageFile<<endl;

cout<<"减少可用进程空间="

<<memStatusVirtual.dwAvailVirtual-memStatusVirtual1.dwAvailVirtual<<endl<<endl;

结果如下:

 

可见,进程空间减少了1G;减少的物理内存和可用页文件用来管理页目和页表。但是,现在访问空间的话,会出错的:

int * iV=(int*)pV;

   //iV[0]=1;现在访问会出错,出现访问违规

 

·        提交

你必须提供一个初始地址和提交的大小。提交的大小系统会变成页面的倍数,因为只能按页面提交。指定类型是MEM_COMMIT。保护属性最好跟区域的保护属性一致,这样可以提高系统管理的效率。

C++程序:提交100M的空间

LPVOID pP=VirtualAlloc(pV,100*1024*1024,MEM_COMMIT,PAGE_READWRITE);    

            if(pP==NULL)

            cout<<"没有那么多物理空间!"<<endl;

            int * iP=(int*)pP;

            iP[0]=3;

            iP[100/sizeof(int)*1024*1024-1]=5;//这是能访问的最后一个地址

            //iP[100/sizeof(int)*1024*1024]=5;访问出错

  

·        保留&提交

你可以用类型MEM_RESERVE|MEM_COMMIT一次全部提交。但是这样的话,没有有效地利用内存,和使用一般的C++动态分配内存函数一样了。

 

·        更改保护属性

更改已经提交的页面的保护属性,有时候会很有用处,假设你在访问数据后,不想别的函数再访问,或者出于防止指针乱指改变结构的目的,你可以更改数据所处的页面的属性,让别人无法访问。

VirtualProtect (PVOID 基地址,SIZE_T 大小,DWORD 新属性,DWORD 旧属性)

基地址是你想改变的页面的地址,注意,不能跨区改变。

C++

  • 2
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值