Windows内存管理及C++语言内存分配.docx

上传人:无*** 文档编号:91458450 上传时间:2023-05-26 格式:DOCX 页数:87 大小:149.80KB
返回 下载 相关 举报
Windows内存管理及C++语言内存分配.docx_第1页
第1页 / 共87页
Windows内存管理及C++语言内存分配.docx_第2页
第2页 / 共87页
点击查看更多>>
资源描述

《Windows内存管理及C++语言内存分配.docx》由会员分享,可在线阅读,更多相关《Windows内存管理及C++语言内存分配.docx(87页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、Windows内存管理及C+语言内存分配本文背景:在编程中,很多Windows或C+的内存函数不知道有什么区别,更别谈有效使用; 根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结 描述,结合实例来阐明这个机制。本文目的:对Windows内存管理机制了解清楚,有效的利用C+内存函数管理和使用内存。本文内容:本文一共有六节,由于篇幅较多,故按节发表。其他章节请看本人博客的Windows 内存管理及C+内存分配实例(二)(三)(四)(五)和(六)。1 .进程地址空间1.1 地址空间 32164位的系统ICPU操作系统运行在硬件CPU上,32位操作系统运行于32位CPU上,6

2、4位 操作系统运行于64位CPU上;目前没有真正的64位CPU。32位CPU一次只能操作32位二进制数;位数多CPU设计越复杂,软件设计 越简单。软件的进程运行于32位系统上,其寻址位也是32位,能表示的空间是 232=4G,范围从 0x0000 000OxFFFF FFFF。 NULL指针分区范围:0x0000 0000-0x0000 FFFF作用:保护内存非法访问例子:分配内存时,如果由于某种原因分配不成功,则返回空指针0x0000 0000; 当用户继续使用比如改写数据时,系统将因为发生访问违规而退出。那么,为什么需要那么大的区域呢,“个地址值不就行了吗?我在想,是 不是因为不让8或16

3、位的程序运行于32位的系统上呢? !因为NULL分区刚 好范围是16的进程空间。 独享用户分区范围:0x0001 00000x7FFE FFFF作用:进程只能读取或访问这个范围的虚拟地址;超越这个范围的行为都会产 生违规退出。例子:程序的二进制代码中所用的地址大部分将在这个范围,所有exe和dll文 件都加载到这个。每个进程将近2G的空间是独享的。注意:如果在boot.ini上设置了/3G,这个区域的范围从2G扩大为3G: 0x0001 00000xBFFE FFFF。 共享内核分区范围:0x8000 00000xFFFF FFFF作用:这个空间是供操作系统内核代码、设备驱动程序、设备1/O高

4、速缓存、 非页面内存池的分配、进程目表和页表等。例子:这段地址各进程是可以共享的。注意:如果在boot.ini上设置了/3G,这个区域的范围从2G缩小为1G: OxCOOO 00000xFFFF FFFF 通过以上分析,可以知道,如果系统有n个进程,它所需的虚拟空间是: 2G*n+2G (内核只需2G的共享空间)。1.2 地址映射 区域区域指的是上述地址空间中的片连续地址。区域的大小必须是粒度(64k)的 整数倍,不是的话系统自动处理成整数倍。不同CPU粒度大小是不样的, 大部分都是64Ko区域的状态有:空闲、私有、映射、映像。在你的应用程序中,申请空间的过程称作保留(预订),可以用Virtu

5、alAlloc;删 除空间的过程为释放,可以用VirtualFree。在程序里预订了地址空间以后,你还不可以存取数据,因为你还没有付钱, 没有真实的RAM和它关联。这时候的区域状态是私有;默认情况下,区域状态是空闲:当exe或DLL文件被映射进了进程空间后,区域状态变成映像;当一般数据文件被映射进了进程空间后,区域状态变成映射。 物理存储器Windows各系列支持的内存上限是不样的,从2G到64G不等。理论上32 位CPU,硬件上只能支持4G内存的寻址;能支持超过4G的内存只能靠其他 技术来弥补。顺便提,下,Windows个人版只能支持最大2G内存,Intel使用 Address Window

6、s Extension (AWE)技术使得寻址范围为236=64G=当然,也得 操作系统配合。内存分配的最小单位是4K或8K, -一般来说,根据CPU不同而不同,后 面你可以看到可以通过系统函数得到区域粒度和页面粒度。 页文件页文件是存在硬盘上的系统文件,它的大小可以在系统属性里面设置,它相当 于物理内存,所以称为虚拟内存。事实上,它的大小是影响系统快慢的关键所 在,如果物理内存不多的情况下。每页的大小和上述所说内存分配的最小单位是样的,通常是4K或8K。 访问属性物理页面的访问属性指的是对页面进行的具体操作:可读、可写、可执行。CPU 一般不支持可执行,它认为可读就是可执行。但是,操作系统提

7、供这个可执行 的权限。PAGE_NOACCESS PAGE_READONLY PAGE_READWRITE PAGE_EXECUTE PAGE_EXECUTE_READ PAGE_EXECUTE_READWRITE 这6个属性很好理解,第一个是拒绝所有操作,最后一个是接受收有操作; PAGE_WRITECOPYPAGE_EXECUTE_WRITECOPY这两个属性在运行同一个程序的多个实例时非常有用;它使得程序可以共享代 码段和数据段。一般情况下,多个进程只读或执行页面,如果要写的话,将会 Copy页面到新的页面。通过映射exe文件时设置这两个属性可以达到这个目 的。PAGE_NOCACHEP

8、AGE WRITECOMBINE这两个是开发设备驱动的时候需要的。PAGE GUARD当往页面写入个字节时,应用程序会收到堆栈溢出通知,在线程堆栈时有用。映射过程进程地址空间的地址是虚拟地址,也就是说,当取到指令时,需要把虚拟地址 转化为物理地址才能够存取数据。这个工作通过页目和页表进行。页表:111024102410241页目:从图中可以看出,页目大小为4K,其中每项(32位)保存个页表的物理地 址;每个页表大小为4K,其中每项(32位)保存一个物理页的物理地址, 共有1024个页表。利用这4K+4K*1K=4.4M的空间可以表示进程的1024*1024* (页4K) =4G的地址空间。进程

9、空间中的32位地址如下:高10位中10位低12位高10位用来找到1024个页目项中的项,取出页表的物理地址后,利用中!0位来得到页表项的值,根据这个值得到物理页的地址,由于页有4K大小, 利用低12位得到单元地址,这样就可以访问这个内存单元了。每个进程都有自己的个页目和页表,那么,刚开始进程是怎么找到页目 所在的物理页呢?答案是CPU的CR3寄存器会保存当前进程的页目物理地址。当进程被创建时,同时需要创建页目和页表,一共需要4.4M。在进程的 空间中,OxCO3O 00000xC030 OFFF是用来保存页目的4k空间。OxCOOO 00000xC03F FFFF是用来保存页表的4M空间。也就

10、是说程序里面访问这些 地址你是可以读取页目和页表的具体值的(要工作在内核方式下)。有一点我 不明白的是,页表的空间包含了页目的空间!至于说,页目和页表是保存在物理内存还是页文件中,我觉得,页目比较 常用,应该在物理内存的概率大点,页表需要时再从页文件导入物理内存中。页目项和页表项是个32位的值,当页目项第位为1时,表明页表已 经在物理内存中;当页表项第位为1时,表明访问的数据已经在内存中。还 有很多数据是否已经被改变,是否可读写等标志。另外,当页目项第7位为1 时,表明这是个4M的页面,这值已经是物理页地址,用虚拟地址的低22 位作为偏移量。还有很多:数据是否已经被改变、是否可读写等标志。1.

11、3 个例子 编写生成软件程序exe软件描述如下:Main ()(1:定义全局变量2:处理函数逻辑(Load所需DLL库,调用方法处理逻辑)3:定义并实现各种方法(方法含有局部变量)4:程序结束将程序编译,生成exe文件,附带所需的DLL库。 exe文件格式exe文件有自己的格式,有若干节(section) : .text用来放二进制代码(exe 或dll) ; .data用来放各种全局数据。.text指令 1 : move a, b指令 2: add a, b.data数据1: a=2数据2: b=l这些地址都是虚拟地址,也就是进程的地址空间。 运行exe程序建立进程:运行这个exe程序时,系

12、统会创建一个进程,建立进程控制块 PCB,生成进程页目和页表,放到PCB中。数据对齐:数据的内存地址除以数据的大小,余数为时说明数据是对齐 的。现在的编译器编译时就考虑数据对齐的问题,生成exe文件后,数据 基本上是对齐的,CPU运行时,寄存器有标志标识CPU是否能够自动对 齐数据,如果遇到不能对齐的情况,或者通过两次访问内存,或者通知操 作系统处理。要注意的是,如果数据没有对齐,CPU处理的效率是很低的。文件映射:系统不会将整个exe文件和所有的DLL文件装载进物理内存中, 同时它也不会装载进页面文件中。相反,它会建立文件映射,也就是利用 exe本身当作页面文件。系统将部分二进制代码装载进内

13、存,分配页面给 它。假设分配了一个页面,物理地址为0x0232 FFF1。其中装载的个指 令虚拟地址为 0x4000 1001=0100 0000 00 0000 0000 01 0000 0000 0001 个页面有4K,系统会将指令保存在低12位0x0001的地址处。同时,系统 根据高10位0x0100找到页目项,如果没有关联的页表,系统会生成一个 页表,分配个物理页;然后,根据中10位0x0001找到表项,将物理地 址0x0232 FFF!存进去。执行过程:执行时,当系统拿到个虚拟地址,就根据页目和页表找到数据的地址, 根据页目上的值可以判断页表是在页文件中还是在内存中;如果在页文件中,

14、会将页面导入内存,更新页目项。读取页表项的值后, 可以判断数据页文件中还是在物理内存中;如果在页文件中,会导入到内 存中,更新页表项。最终,拿到了数据。在分配物理页的过程中,系统会根据内存分配的状况适当淘汰暂时不 用的页面,如果页面内容改变了(通过页表项的标志位),保存到页文件 中,系统会维护内存与页文件的对应关系。由于将exe文件当作内存映射文件,当需要改变数据,如更改全局变量的 值时,利用Copy-On-Write的机制,重新生成页文件,将结果保存在这个 页文件中,原来的页文件还是需要被其他进程实例使用的。在清楚了指令和数据是如何导入内存,如何找到它们的情况下,剩下 的就是CPU不断的取指

15、令、运行、保存数据的过程了,当进程结束后,系 统会清空之前的各种结构、释放相关的物理内存和删除页文件。2 .内存状态査询函数2.1 系统信息Windows提供API可以查询系统内存的些属性,有时候我们需要获取些页 面大小、分配粒度等属性,在分配内存时用的上。请看以下C+程序:SYSTEMJNFO syslnfo;GetSystemInfo(&sysInfo);coutvv”机器属性: vvendl;coutvv页 大小sysInfo.dwPageSizevvendl;cout”分酉己粒度二sysInfo.dwAllocationGranularityvvendl;cout”用户区最小值=sys

16、Info.lpMinimumApplicationAddressendl;cout”用户区最大值=”sysInfo.lpMaximumApplicationAddressendlendI;结果如下:负大小=4096分配粒廬=65536用户区曇值=00010000用户区最大值=7FFEFFFF可以看出,页面大小是4K,区域分配粒度是64K,进程用户区是0x000100000x7FFE FFFF。2.2 内存状态内存状态可以获取总内存和可用内存,包括页文件和物理内存。 请看以下C+程序:MEMORYSTATUS memStatus;GlobalMemoryStatus(&memStatus);co

17、utvv”内存初始状态:“ vvendl;coutvv” 内存繁忙程度二 vvmemStatus.dwMemoryLoadvvendl;coutvv”总物理内存=vvmemStatus.dwTotalPhysvvendl;coutvv”可用物理内 d=,memStatus.dwAvailPhysendl;coutvv”总页文件二 vvmemStatus.dwTotalPageFilevvendl;cout,rnj 用页文件二 vvmemS tatus.d w A vai 1 PageFileendl;coutvv”总进程空间二” vvmemStatus.dwTotalVirtuakvendl;

18、coutvv” 可用进程空间二” vvmemStatus.dwAvailVirtualvvendkvendl; 结果如下:2 0 7 8 4 0 6 2 0 4 4 7 4 4 5 2 0 5 1 7 2 19 2 2 15 9 5 5 4 0 0 2 3 3 2 2 2 10 8 7 1 5 7 5 7 5 4 2 .=0 = 791 = 态度=1存57=1=2间 薈存内=2在空 始忙内理件文空程 初繁理物文豊进 存居用 内内总司总可总可可以看出,总物理内存是1G,可用物理内存是510兆,总页文件是2.5G,这个 是包含物理内存的页文件;可用页文件是1.9G。这里还标识了总进程空间,还有 可

19、用的进程空间,程序只用了 22兆的内存空间。这里说的都是大约数。内存繁忙程序是标识当前系统内存管理的繁忙程序,从。到100,其实用处不大。在函数里而静态分配些内存后,看看究竟发生什么char statf65536;MEMORYSTATUS memStatus 1;GlobalMemoryStatus(&memStatus 1);coutvv”静态分配空间:nendl;printf(”指针地址二x/n”,stat);coutv”减少物理内存二” vvmemStatus.dwAvailPhys-memStatusl.dwAvailPhysvvendl;coutv减少可用页文件=,memStatus

20、.dwAvailPageFile-memStatusl.dwAvailPageFileendl;coutvv”减少可用进程空间 vvmemStatus.dwAvailVirtuamemSta tusl.dwAvailVirtualendlendl;结果如下:C=0间 :e0=0件空 间2f存文程 空=1受进 配址理用用 分地物可可 态针少少少 建减减减可以看出,物理内存、可用页文件和进程空间都没有损耗。因为局部变量是分配 在线程堆栈里面的,每个线程系统都会建立一个默认1M大小的堆栈给线程函数 调用使用。如果分配超过1M,就会出现堆栈溢出。 在函数里面动态分配300M的内存后,看看究竟发生什么c

21、har *dynamic=new char300* 1024* 1024;MEMORY ST ATUS memStatus2;GlobalMemoryStatus(&memStatus2);coutvv”动态分配空间:nendl;printf(指针地址二x/n”,dynamic);coutvv”减少物理内存=nmemStatus.dwAvailPhys-memStatus2.dwAvailPhysendl;coutvv”减少可用页文件=,memStatus.dwAvailPageFile-memStatus2.dwAvailPageFileendl;coutvv”减少可用进程空间=,memSt

22、atus.dwAvailVirtuaI-memStatus2.dwAvailVirtualendlendl;结果如下:指 针地址=105 40040减少物理内存=315551744 减少可用页文件=315518976減少可用进程空间=314576896动态分配情况下,系统分配直到内存页文件使用完为止,当然,系统要留下系 统使用的页面。2.3进程区域地址査询在给定一个进程空间的地址后,可以查询它所在区域和相邻页面的状态,包括页 面保护属性、存储器类型等。 C+静态分配了两次内存,一次是4K大一点,个是900K左右。char arrayA 4097;char arrayB 900000;第一次查询

23、:long len=sizeof(MEMORY_BASICJNFORMATION);MEMORY_BASICNFORMATION mbiA;VirtualQuery(arrayA,&mbiA,len);coutv v”静态内存地址属性: vvendl;coutvv”区域基地址二 vvmbiA.AHocationBasevvendl;coutvv”区域邻近页面状态=” vvmbi A.State vvendl;coutvv”区域保护属性=”vvmbiA.AllocationProtectvvendl;coutvv”页面基地址二” vvmbiA.BaseAddressvvendl;printf(n

24、arrayA 指针地址二x/n”,array A);coutv V”从页面基地址开始的大小二”号mbi A. RegionSizevvendl;cout”邻近页面物理存储器类型二”mbiA.Typevvendl;cout”页面保护属性二”mbiA.Protectendlendl;第二次查询:MEMORY_BASICNFORMATION mbiB;VirtuaIQuery(arrayB,&mbiB,len);cout”静态内存地址属性:”endl;cout”区域基地址二”mbiB.AllocationBasevvendl;cout”区域邻近页面状态二”mbiB.Statevvendl;cout”

25、区域保护属性二”mbiB.AllocationProtectvvendl;cout”页面基地址二”mbiB.BaseAddressvvendl;printf(arrayB 指针地址二x/n”,arrayB);cout”从页面基地址开始的大小二”mbiB.RegionSizevvendl;cout邻近页面物理存储器类型=mbiB.Typeendl;cout页面保护属性=mbi B.Protectendlendl;说明:区域基地址指的是给定地址所在的进程空间区域;邻近页面状态指的是与给定地址所在页面状态相同页面的属性:MEM_FREE(空 闲=65536)、MEM_RESERVE (保留=8192

26、)和 MEM_COMMIT (提交=4096) 区域保护属性指的是区域初次被保留时被赋予的保护属性:PAGE_READONLY(2)、PAGE_READWRITE (4)、PAGE_WRITECOPY (8)和PAGE_EXECUTE_WRITECOPY (128)等等。页面基地址指的是给定地址所在页面的基地址。从页面基地址开始的区域页面的大小,指的是与给定地址所在页面状态、保护属 性相同的页面。邻近页面物理存储器类型指的是与给定地址所在页面相同的存储器类型,包括: MEM_PRIVATE (页文件=131072) MEM_MAPPED (文件映射=262144)和 MEM_IMAGE (ex

27、e 映像=16777216) 页面保护属性指的是页面被指定的保护属性,在区域保护属性指定后更新。结果如下:“区区区页 静区区区页属00状=401址开存=4 址=0面性=0地址理性 地址賈址 靠近护地指基面护 内基邻保基W面页保 态域域域面ra页近面性40态004094小型00 e内皆 0 2F32E=1始储性40态53=5始储 属00状=400址开存=4 址=0面性=0地址理性 地址置址気闇 壶近护地指基面护 内基邻保基VB面页保 态域域域面raK近面00409如前所说,这是在堆栈区域0x0004 0000里分配的,后分配的地址arrayB反而更 小,符合堆栈的特性。arrayA和arrayB

28、它们处于不同的页面。页面都受页文件 支持,并且区域都是提交的,是系统在线程创建时提交的。 C+动态分配了两次内存,一次是1K大一点,个是64K左右。所以应该 不会在个区域。char *dynamicA=new char1024;char *dynamicB=new charf65467;VirtuaIQuery(dynamicA,&mbiA,len);coutn动态内存地址属性:nendl;coutvv”区域基地址=vmbiA.AllocationBasevvendl;coutH 区域邻近页面状态=mbi A.Stateendl;coutv”区域保护属性 vvmbiA.AHocationPro

29、tectvvendl;coutvv”页面基地址=vmbiA.BaseAddressvvendl;printf(ndynamicA 指针地址二x/n”,dynamicA);coutvv”从页面基地址开始的大小二” vvmbiA.RegionSizevvendl;coutvv”邻近页而物理存储器类型二 vvmbiA.Typevvendl;coutn 页面 保护属 性=vvmbiA.Protectv vendk vendl;VirtualQuery(dynamicB,&mbiB,len);coutvv”动态内存地址属性:” vvendl;coutvv”区域基地址二” vvmbiB.AHocation

30、Basevvendl;coutvv”区域邻近页面状态二” vvmbiB.Statevvendl;coutvv” 区域保护 属性二” vvmbiB.AllocationProtectvvendl;coutvv” 页面基地址二” vvmbiB.BaseAddressvvendl;printf(dynamicB 指针地址二x/n”,dynamicB);coutvv”从页面基地址开始的大小二” vvmbiB.RegionSizevvendl;coutvv”邻近页面物理存储器类型二” vvmbiB.Typevvendl;coutn 页面保护属性二” vvmbi B. Protectv vendl;结果如

31、下:态域域域面na页近面内基邻保基mi面页保拿近护地CA基面护属00状=400地开存=4 址=0面性=0苴理性 地址址指地鷲性30态aw 0 9 4/4 -0 3勺S 0 =自口 39址始储个=8192 型=131072态域域域面na页近面内基邻保基mi面血保近护地CB基面护属0E状=40E地开存=4 址=0面性=0基理性 地址費址指地闇性10态0601 0 14/4- 00=e的器 10址始储236 9这里是动态分配,dynamicA和dynamicB处于两个不同的区域;同样,页面都受 页文件支持,并且区域都是提交的。第二个区域是比64K大的,由分配粒度可知,区域至少是128K。那么,剩下的

32、 空间也是提交的吗,如果是的话那就太浪费了。看看就知道了: 0x00E2 1000 n 定在这个空间里,所以查询如下:VirtualQuery(char*)0xE23390,&mbiB,len);cout动态内存地址属性:endl;cout区域 基地址=mbi B. Al locationBaseendl;cout区域邻近页面状态=mbiB.Stateendl;cout区域保护 属性=mbiB.AHocationProtectendl;cout页面基地址=mbi B. BaseAddressendl;printf(dynamicB 指针地址=%x/n,0xE2100);cout从页面基地址开始

33、的大小=mbiB.RegionSizeendl;cout邻近页面物理存储器类型=mbiB.Typeendl;cout页面保护属性=mbi B.Protectendl;结果如下:属0E状=40E地开存=0 址=0面性=0基理性 地址畫址指地闇 拿近护地CB基面护 内基邻保基mi面页保 态域域域面na页近面 区区页My从矇性10态21址始储00的器0 = 00! 0 2.可以看出,邻近页面状态为保留,还没提交,预料之中;OxOOEl 0000这个区域 的大小可以计算出来:69632+978944=1024Ko系统动态分配了 1M的空间,就 为了 64K左右大小的空间。可能是为了使得下次有要求分配时

34、时不用再分配了。3.内存管理机制一虚拟内存(VM) 虚拟内存使用场合虚拟内存最适合用来管理大型对象或数据结构。比如说,电子表格程序,有很多 单元格,但是也许大多数的单元格是没有数据的,用不着分配空间。也许,你会 想到用动态链表,但是访问又没有数组快。定义二维数组,就会浪费很多空间。 它的优点是同时具有数组的快速和链表的小空间的优点。 分配虚拟内存如果你程序需要大块内存,你可以先保留内存,需要的时候再提交物理存储器。 在需要的时候再提交能有效的利用内存。一般来说,如果需要内存大于1M, 用虚拟内存比较好。 保留用以下Windows函数保留内存块VirtualAlloc(PVOID 开始地址,SI

35、ZE_T 大小,DWORD 类型,DWORD 保护属 性)一般情况下,你不需要指定“开始地址,因为你不知道进程的那段空间是不是已 经被占用了;所以你可以用NULL。“大小”是你需要的内存字节;“类型”有 MEM_RESERVE (保留)、MEM.RELEASE (释放)和 MEM.COMMIT (提交)。 “保护属性”在前面章节有详细介绍,只能用前六种属性。如果你要保留的是长久不会释放的内存区,就保留在较高的空间区域,这样不会 产生碎片。用这个类型标志可以达到;MEM RESERVEIMEM TOP DOWN C+程序:保留1G的空间LPVOIDpV=VirtualAlloc(NULL,l 0

36、00*1024*1024,MEM_RESERVEIMEM_TOP_DOWN, PAGE_READWRITE);if(pV=NULL)cout没有那么多虚拟空间!endl;MEMORYSTATUS memStatusVirtual 1;GlobalMemoryStatus(&memStatusVirtual 1);cout虚拟内存分配:endl;printf(指针地址=%x/n,pV);cout减少物理内存=memStatusVirtual.dwAvailPhys-memStatus Virtual 1 .dwAvailPhysendl;cout减少可用页文件=memStatusVirtual.

37、dwAvailPageFile-memStatusVirtuall .dwAvaiIPageFilee ndl;cout减少可用进程空间=memStatusVirtual.dwAvailVirtual-memStatusVirtuall .dwAvailVirtualendl endl;结果如下:配41存文程 分=2亨逬 盘理用用 内地物可可 虚指减减减C63=2间=1呈可见,进程空间减少了 1G;减少的物理内存和可用页文件用来管理页目和页表。 但是,现在访问空间的话,会出错的:int * iV=(int*)pV;/iV01= 1;现在访问会出错,出现访问违规你必须提供个初始地址和提交的大小。

38、提交的大小系统会变成页面的倍数,因 为只能按页面提交。指定类型是MEM_COMMIT。保护属性最好跟区域的保护 属性一致,这样可以提高系统管理的效率。C+程序:提交100M的空间LPVOIDpP=VirtualAlloc(pV,l 00* 1024* 1024,MEM_COMMIT,PAGE_READWRITE);if(pP=NULL)cout没有那么多物理空间!”endl;int * iP=(int*)pP;iP0=3;iP 100/sizeof(int)* 1024* 1024-1=5;这是能访问的最后个地址/iPl 00/sizeof(int)*l024* 1024=5;访问出错 保留&

39、提交你可以用类型MEM_RESERVEIMEM_COMMIT 一次全部提交。但是这样的话, 没有有效地利用内存,和使用一般的C+动态分配内存函数一样了。 更改保护属性更改已经提交的页面的保护属性,有时候会很有用处,假设你在访问数据后,不 想别的函数再访问,或者出于防止指针乱指改变结构的目的,你可以更改数据所 处的页面的属性,让别人无法访问。VirtualProtect(PVOID 基地址,SIZE_T 大小,DWORD 新属性,DWORD 旧属性) “基地址”是你想改变的页面的地址,注意,不能跨区改变。C+程序:更改页的页面属性,改为只读,看看还能不能访问DWORD protect;iP0=8

40、;VirtualProtect(pV,4096,PAGE_READONLY,&protect);int * iP=(int*)pV;iP1024=9;可以访问,因为在那页之外iP0=9;不可以访问,只读还原保护属性VirtualProtect(pV,4096,PAGE_READWRITE,&protect);cout初始值=iPc(PVOID 开始地址,SIZE_T 大小,DWORD 类型,DWORD 保护属 性)“大小”如果小于个页面的话,函数会执行失败,因为系统使用四舍五入的方法;“类型,是 MEM_RESETo有人说,为什么需要清除呢,释放不就行了吗?你要知道,释放了后,程序就无 法访问

41、了。现在只是因为不需要结构的内容了,顺便提高一下系统的性能;之后 程序仍然需要访问这个结构的。C+程序:清除1M的页面:PVOIDre=VirtuaiAlioc(pV, 1024*1024,MEM_RESET,PAGE_READWRITE); if(re=NULL)cout清除失败! ”endl;这时候,页面可能还没有被清零,因为如果系统没有RAM请求的话,页面内存 保存不变的,为了看看被清零的效果,程序人为的请求大量页面: C+程序:VirtualAlloc(char*)pV+100*1024* 1024+4096,memStatus.dwAvailPhys+1000000 ,MEM_COM

42、Mrr,PAGE_READWRITE); 没访问之前是不给物理内存的。char* pp=(char*)pV+100* 1024* 1024+4096;for(int i=O;imemStatus.dwAvailPhys+10000000;i+)PPi=V;逼他使用物理内存,而不使用页文件 GlobalMemoryStatus(&memStatus);cout内存初始状态:endl;cout-|x;Jx=memStatus.dwLengthendl;cout”内存繁忙 程度=memStatus.dwMemoryLoadendl;cout总物理内 #=memStatus.dwTotalPhysen

43、dl;cout可用物理内 ir=memStatus.dwAvailPhysendl;cout“总页文件=memStatus.dwTotaIPageFileendl;cout”可用页文件=memStatus.dwAvailPageFileendl;cout”总进程空间=memStatus.dwTotalVirtualendl;cout可用进程空间=memStatus.dwAvailVirtualend;cout清除后=iP endl;结果如下:6 4 ? 8 6 8 6 1 0 6 0 7 4 4 7 2 0 5 3 7 7 19 2 6 19 9 15 5 0 0 2 8 3 7 3 2 0

44、0 3 7 0 :=507=577641 4=1 态度=1存57=1=2间 状程存内=2空 =8始2忙内理件文空程 鳴=3聲理物文豊逬 始存豊覇用 初内长内总可总可总可态 6 rtr =0 = 711 = 的度=1存57=1=2间 时程存内=2舊空 零2忙内理件文空程=0 清=3繁理物文矗逬后 入豊爲 逬长内总可总可总可清当内存所剩无儿时,系统将刚清除的内存页面分配出去,同时不会把页面的内存 写到虚拟页面文件中。可以看见,原先是8的值现在是。 了。 虚拟内存的关键之处虚拟内存存在的优点是,需要的时候真正分配内存。那么程序必须决定何时 提交内存。如果访问没有提交内存的数据结构,系统会产生访问违规

45、的错误。提交的最好方 法是,当你程序需要访问虚拟内存的数据结构时,假设它已经是分配内存的,然 后异常处理可能出现的错误。对于访问违规的错误,就提交这个地址的内存。释放可以释放整个保留的空间,或者只释放分配的些物理内存。释放特定分配的物理内存:如果不想释放所有空间,可以只释放某些物理内存。“开始地址”是页面的基地址,这个地址不一定是第一页的地址,个窍门是提供 页中的某个地址就行了,因为系统会做页边界处理,取该页的首地址;“大小 是页面的要释放的字节数;“类型”是MEM.DECOMMIToC+程序:只释放物理内存VirtualFree(int*)pV+2OOO,5O* 1024* 1024,MEM_DECOMMIT);int* a=(int*)pV;a10=2,可以使用,没有释放这页MEMORYSTATUS memStatusVirtual3;GlobalMem

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 教案示例

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com