日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

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

發(fā)布時(shí)間:2025/3/15 c/c++ 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 全面介绍Windows内存管理机制及C++内存分配实例(三):虚拟内存 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文背景:

在編程中,很多Windows或C++的內(nèi)存函數(shù)不知道有什么區(qū)別,更別談?dòng)行褂?#xff1b;根本的原因是,沒(méi)有清楚的理解操作系統(tǒng)的內(nèi)存管理機(jī)制,本文企圖通過(guò)簡(jiǎn)單的總結(jié)描述,結(jié)合實(shí)例來(lái)闡明這個(gè)機(jī)制。

本文目的:

對(duì)Windows內(nèi)存管理機(jī)制了解清楚,有效的利用C++內(nèi)存函數(shù)管理和使用內(nèi)存。

本文內(nèi)容:

本文一共有六節(jié),由于篇幅較多,故按節(jié)發(fā)表。其他章節(jié)請(qǐng)看本人博客的Windows內(nèi)存管理及C++內(nèi)存分配實(shí)例(一)(二)(四)(五)和(六)。

?

3.??????內(nèi)存管理機(jī)制--虛擬內(nèi)存?(VM)

·????????虛擬內(nèi)存使用場(chǎng)合

虛擬內(nèi)存最適合用來(lái)管理大型對(duì)象或數(shù)據(jù)結(jié)構(gòu)。比如說(shuō),電子表格程序,有很多單元格,但是也許大多數(shù)的單元格是沒(méi)有數(shù)據(jù)的,用不著分配空間。也許,你會(huì)想到用動(dòng)態(tài)鏈表,但是訪問(wèn)又沒(méi)有數(shù)組快。定義二維數(shù)組,就會(huì)浪費(fèi)很多空間。

它的優(yōu)點(diǎn)是同時(shí)具有數(shù)組的快速和鏈表的小空間的優(yōu)點(diǎn)。

?

·????????分配虛擬內(nèi)存

如果你程序需要大塊內(nèi)存,你可以先保留內(nèi)存,需要的時(shí)候再提交物理存儲(chǔ)器。在需要的時(shí)候再提交才能有效的利用內(nèi)存。一般來(lái)說(shuō),如果需要內(nèi)存大于1M,用虛擬內(nèi)存比較好。

?

·????????保留

用以下Windows?函數(shù)保留內(nèi)存塊

VirtualAlloc (PVOID?開(kāi)始地址,SIZE_T?大小,DWORD?類型,DWORD?保護(hù)屬性)

一般情況下,你不需要指定“開(kāi)始地址”,因?yàn)槟悴恢肋M(jìn)程的那段空間是不是已經(jīng)被占用了;所以你可以用NULL。“大小”是你需要的內(nèi)存字節(jié);“類型”有MEM_RESERVE(保留)、MEM_RELEASE(釋放)和MEM_COMMIT(提交)?!氨Wo(hù)屬性”在前面章節(jié)有詳細(xì)介紹,只能用前六種屬性。

如果你要保留的是長(zhǎng)久不會(huì)釋放的內(nèi)存區(qū),就保留在較高的空間區(qū)域,這樣不會(huì)產(chǎn)生碎片。用這個(gè)類型標(biāo)志可以達(dá)到:

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<<"沒(méi)有那么多虛擬空間!"<<endl;

????????????MEMORYSTATUS memStatusVirtual1;

????????????GlobalMemoryStatus(&memStatusVirtual1);

????????????cout<<"虛擬內(nèi)存分配:"<<endl;

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

cout<<"減少物理內(nèi)存="<<memStatusVirtual.dwAvailPhys-memStatusVirtual1.dwAvailPhys<<endl;

cout<<"減少可用頁(yè)文件="<<memStatusVirtual.dwAvailPageFile-memStatusVirtual1.dwAvailPageFile<<endl;

cout<<"減少可用進(jìn)程空間="

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

結(jié)果如下:

?

可見(jiàn),進(jìn)程空間減少了1G;減少的物理內(nèi)存和可用頁(yè)文件用來(lái)管理頁(yè)目和頁(yè)表。但是,現(xiàn)在訪問(wèn)空間的話,會(huì)出錯(cuò)的:

int?* iV=(int*)pV;

???//iV[0]=1;現(xiàn)在訪問(wèn)會(huì)出錯(cuò),出現(xiàn)訪問(wèn)違規(guī)

?

·????????提交

你必須提供一個(gè)初始地址和提交的大小。提交的大小系統(tǒng)會(huì)變成頁(yè)面的倍數(shù),因?yàn)橹荒馨错?yè)面提交。指定類型是MEM_COMMIT。保護(hù)屬性最好跟區(qū)域的保護(hù)屬性一致,這樣可以提高系統(tǒng)管理的效率。

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

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

????????????if(pP==NULL)

????????????cout<<"沒(méi)有那么多物理空間!"<<endl;

????????????int?* iP=(int*)pP;

????????????iP[0]=3;

????????????iP[100/sizeof(int)*1024*1024-1]=5;//這是能訪問(wèn)的最后一個(gè)地址

????????????//iP[100/sizeof(int)*1024*1024]=5;訪問(wèn)出錯(cuò)

??

·????????保留&提交

你可以用類型MEM_RESERVE|MEM_COMMIT一次全部提交。但是這樣的話,沒(méi)有有效地利用內(nèi)存,和使用一般的C++動(dòng)態(tài)分配內(nèi)存函數(shù)一樣了。

?

·????????更改保護(hù)屬性

更改已經(jīng)提交的頁(yè)面的保護(hù)屬性,有時(shí)候會(huì)很有用處,假設(shè)你在訪問(wèn)數(shù)據(jù)后,不想別的函數(shù)再訪問(wèn),或者出于防止指針亂指改變結(jié)構(gòu)的目的,你可以更改數(shù)據(jù)所處的頁(yè)面的屬性,讓別人無(wú)法訪問(wèn)。

VirtualProtect (PVOID?基地址,SIZE_T?大小,DWORD?新屬性,DWORD?舊屬性)

“基地址”是你想改變的頁(yè)面的地址,注意,不能跨區(qū)改變。

C++程序:更改一頁(yè)的頁(yè)面屬性,改為只讀,看看還能不能訪問(wèn)

DWORD protect;

????????????iP[0]=8;

????????????VirtualProtect(pV,4096,PAGE_READONLY,&protect);

????????????int?* iP=(int*)pV;

iP[1024]=9;//可以訪問(wèn),因?yàn)樵谀且豁?yè)之外

????????????//iP[0]=9;不可以訪問(wèn),只讀

????????????//還原保護(hù)屬性

????????????VirtualProtect(pV,4096,PAGE_READWRITE,&protect);

???cout<<"初始值="<<iP[0]<<endl;//可以訪問(wèn)

?

·????????清除物理存儲(chǔ)器內(nèi)容

清除頁(yè)面指的是,將頁(yè)面清零,也就是說(shuō)當(dāng)作頁(yè)面沒(méi)有改變。假設(shè)數(shù)據(jù)存在物理內(nèi)存中,系統(tǒng)沒(méi)有RAM頁(yè)面后,會(huì)將這個(gè)頁(yè)面暫時(shí)寫進(jìn)虛擬內(nèi)存頁(yè)文件中,這樣來(lái)回的倒騰系統(tǒng)會(huì)很慢;如果那一頁(yè)數(shù)據(jù)已經(jīng)不需要的話,系統(tǒng)可以直接使用。當(dāng)程序需要它那一頁(yè)時(shí),系統(tǒng)會(huì)分配另一頁(yè)給它。

VirtualAlloc (PVOID?開(kāi)始地址,SIZE_T?大小,DWORD?類型,DWORD?保護(hù)屬性)

“大小”如果小于一個(gè)頁(yè)面的話,函數(shù)會(huì)執(zhí)行失敗,因?yàn)橄到y(tǒng)使用四舍五入的方法;“類型”是MEM_RESET。

有人說(shuō),為什么需要清除呢,釋放不就行了嗎?你要知道,釋放了后,程序就無(wú)法訪問(wèn)了?,F(xiàn)在只是因?yàn)椴恍枰Y(jié)構(gòu)的內(nèi)容了,順便提高一下系統(tǒng)的性能;之后程序仍然需要訪問(wèn)這個(gè)結(jié)構(gòu)的。

C++程序:

清除1M的頁(yè)面:

PVOID re=VirtualAlloc(pV,1024*1024,MEM_RESET,PAGE_READWRITE);

????????????if(re==NULL)

???cout<<"清除失敗!"<<endl;

這時(shí)候,頁(yè)面可能還沒(méi)有被清零,因?yàn)槿绻到y(tǒng)沒(méi)有RAM請(qǐng)求的話,頁(yè)面內(nèi)存保存不變的,為了看看被清零的效果,程序人為的請(qǐng)求大量頁(yè)面:

C++程序:

VirtualAlloc((char*)pV+100*1024*1024+4096,memStatus.dwAvailPhys+10000000,MEM_COMMIT,PAGE_READWRITE);//沒(méi)訪問(wèn)之前是不給物理內(nèi)存的。???

????????????char* pp=(char*)pV+100*1024*1024+4096;

????????????for(int?i=0;i<memStatus.dwAvailPhys+10000000;i++)

????????????pp[i]='V';//逼他使用物理內(nèi)存,而不使用頁(yè)文件

????????????GlobalMemoryStatus(&memStatus);

????????????cout<<"內(nèi)存初始狀態(tài):"<<endl;

????????????cout<<"長(zhǎng)度="<<memStatus.dwLength<<endl;

????????????cout<<"內(nèi)存繁忙程度="<<memStatus.dwMemoryLoad<<endl;

????????????cout<<"總物理內(nèi)存="<<memStatus.dwTotalPhys<<endl;

????????????cout<<"可用物理內(nèi)存="<<memStatus.dwAvailPhys<<endl;

????????????cout<<"總頁(yè)文件="<<memStatus.dwTotalPageFile<<endl;

????????????cout<<"可用頁(yè)文件="<<memStatus.dwAvailPageFile<<endl;

????????????cout<<"總進(jìn)程空間="<<memStatus.dwTotalVirtual<<endl;

????????????cout<<"可用進(jìn)程空間="<<memStatus.dwAvailVirtual<<end;

???cout<<"清除后="<<iP[0]<<endl;

結(jié)果如下:

?

當(dāng)內(nèi)存所剩無(wú)幾時(shí),系統(tǒng)將剛清除的內(nèi)存頁(yè)面分配出去,同時(shí)不會(huì)把頁(yè)面的內(nèi)存寫到虛擬頁(yè)面文件中。可以看見(jiàn),原先是8的值現(xiàn)在是0了。

?

·????????虛擬內(nèi)存的關(guān)鍵之處

虛擬內(nèi)存存在的優(yōu)點(diǎn)是,需要的時(shí)候才真正分配內(nèi)存。那么程序必須決定何時(shí)才提交內(nèi)存。

如果訪問(wèn)沒(méi)有提交內(nèi)存的數(shù)據(jù)結(jié)構(gòu),系統(tǒng)會(huì)產(chǎn)生訪問(wèn)違規(guī)的錯(cuò)誤。提交的最好方法是,當(dāng)你程序需要訪問(wèn)虛擬內(nèi)存的數(shù)據(jù)結(jié)構(gòu)時(shí),假設(shè)它已經(jīng)是分配內(nèi)存的,然后異常處理可能出現(xiàn)的錯(cuò)誤。對(duì)于訪問(wèn)違規(guī)的錯(cuò)誤,就提交這個(gè)地址的內(nèi)存。

?

·????????釋放

可以釋放整個(gè)保留的空間,或者只釋放分配的一些物理內(nèi)存。

釋放特定分配的物理內(nèi)存:

如果不想釋放所有空間,可以只釋放某些物理內(nèi)存。

“開(kāi)始地址”是頁(yè)面的基地址,這個(gè)地址不一定是第一頁(yè)的地址,一個(gè)竅門是提供一頁(yè)中的某個(gè)地址就行了,因?yàn)橄到y(tǒng)會(huì)做頁(yè)邊界處理,取該頁(yè)的首地址;“大小”是頁(yè)面的要釋放的字節(jié)數(shù);“類型”是MEM_DECOMMIT。

C++程序:

????????????//只釋放物理內(nèi)存

????????????VirtualFree((int*)pV+2000,50*1024*1024,MEM_DECOMMIT);

????????????int* a=(int*)pV;

????????????a[10]=2;//可以使用,沒(méi)有釋放這一頁(yè)

????????????MEMORYSTATUS memStatusVirtual3;

????????????GlobalMemoryStatus(&memStatusVirtual3);

????????????cout<<"物理內(nèi)存釋放:"<<endl;

cout<<"增加物理內(nèi)存="<<memStatusVirtual3.dwAvailPhys-memStatusVirtual2.dwAvailPhys<<endl;

cout<<"增加可用頁(yè)文件="<<memStatusVirtual3.dwAvailPageFile-memStatusVirtual2.dwAvailPageFile<<endl;

???cout<<"增加可用進(jìn)程空間="

<<memStatusVirtual3.dwAvailVirtual-memStatusVirtual2.dwAvailVirtual<<endl<<endl;

結(jié)果如下:

?

可以看見(jiàn),只釋放物理內(nèi)存,沒(méi)有釋放進(jìn)程的空間。

?

釋放整個(gè)保留的空間:

VirtualFree (LPVOID?開(kāi)始地址,SIZE_T?大小,DWORD?類型)

“開(kāi)始地址”一定是該區(qū)域的基地址;“大小”必須是0,因?yàn)橹荒茚尫耪麄€(gè)保留的空間;“類型”是MEM_RELEASE。

C++程序:

VirtualFree(pV,0,MEM_RELEASE);

????????????//a[10]=2;不能使用了,進(jìn)程空間也釋放了

?

????????????MEMORYSTATUS memStatusVirtual4;

????????????GlobalMemoryStatus(&memStatusVirtual4);

????????????cout<<"虛擬內(nèi)存釋放:"<<endl;

cout<<"增加物理內(nèi)存="<<memStatusVirtual4.dwAvailPhys-memStatusVirtual3.dwAvailPhys <<endl;

cout<<"增加可用頁(yè)文件="<<memStatusVirtual4.dwAvailPageFile-memStatusVirtual3.dwAvailPageFile<<endl;

cout<<"增加可用進(jìn)程空間="

<<memStatusVirtual4.dwAvailVirtual-memStatusVirtual3.dwAvailVirtual<<endl<<endl;

結(jié)果如下:

?

整個(gè)分配的進(jìn)程區(qū)域被釋放了,包括所占的物理內(nèi)存和頁(yè)文件。

?

·????????何時(shí)釋放

如果數(shù)組的元素大小是小于一個(gè)頁(yè)面4K的話,你需要記錄哪些空間不需要,哪些在一個(gè)頁(yè)面上,可以用一個(gè)元素一個(gè)Bit來(lái)記錄;另外,你可以創(chuàng)建一個(gè)線程定時(shí)檢測(cè)無(wú)用單元。

?

·????????擴(kuò)展地址AWE

AWE是內(nèi)存管理器功能的一套應(yīng)用程序編程接口?(API)?,它使程序能夠?qū)⑽锢韮?nèi)存保留為非分頁(yè)內(nèi)存,然后將非分頁(yè)內(nèi)存部分動(dòng)態(tài)映射到程序的內(nèi)存工作集。此過(guò)程使內(nèi)存密集型程序(如大型數(shù)據(jù)庫(kù)系統(tǒng))能夠?yàn)閿?shù)據(jù)保留大量的物理內(nèi)存,而不必交換分頁(yè)文件以供使用。相反,數(shù)據(jù)在工作集中進(jìn)行交換,并且保留的內(nèi)存超過(guò)?4 GB?范圍。

對(duì)于物理內(nèi)存小于2G進(jìn)程空間時(shí),它的作用是:不必要在物理內(nèi)存和虛擬頁(yè)文件中交換。

對(duì)于物理內(nèi)存大于2G進(jìn)程空間時(shí),它的作用是:應(yīng)用程序能夠訪問(wèn)的物理內(nèi)存大于2G,也就相當(dāng)于進(jìn)程空間超越了2G的范圍;同時(shí)具有上述優(yōu)點(diǎn)。

3GB

當(dāng)在boot.ini?上加上?/3GB?選項(xiàng)時(shí),應(yīng)用程序的進(jìn)程空間增加了1G,也就是說(shuō),你寫程序時(shí),可以分配的空間又增大了1G,而不管物理內(nèi)存是多少,反正有虛擬內(nèi)存的頁(yè)文件,大不了慢點(diǎn)。

PAE

當(dāng)在boot.ini上加上?/PAE?選項(xiàng)時(shí),操作系統(tǒng)可以支持大于4G的物理內(nèi)存,否則,你加再多內(nèi)存操作系統(tǒng)也是不認(rèn)的,因?yàn)楣芾磉@么大的內(nèi)存需要特殊處理。所以,你內(nèi)存小于4G是沒(méi)有必要加這個(gè)選項(xiàng)的。注意,當(dāng)要支持大于16G的物理內(nèi)存時(shí),不能使用/3G選項(xiàng),因?yàn)?#xff0c;只有1G的系統(tǒng)空間是不能管理超過(guò)16G的內(nèi)存的。

AWE

當(dāng)在boot.ini上加上?/AWE選項(xiàng)時(shí),應(yīng)用程序可以為自己保留物理內(nèi)存,直接的使用物理內(nèi)存而不通過(guò)頁(yè)文件,也不會(huì)被頁(yè)文件交換出去。當(dāng)內(nèi)存大于3G時(shí),就顯得特別有用。因?yàn)榭梢猿浞掷梦锢韮?nèi)存。

當(dāng)物理內(nèi)存大于4G時(shí),需要/PAE的支持。

以下是一個(gè)boot.ini的實(shí)例圖,是我機(jī)器上的:

?

?

?

要使用AWE,需要用戶具有Lock Pages in Memory權(quán)限,這個(gè)在控制面板中的本地計(jì)算機(jī)政策中設(shè)置。

第一,分配進(jìn)程虛擬空間:

VirtualAlloc (PVOID?開(kāi)始地址,SIZE_T?大小,DWORD?類型,DWORD?保護(hù)屬性)

“開(kāi)始地址”可以是NULL,由系統(tǒng)分配進(jìn)程空間;“類型”是MEM_RESERVE|MEM_PHYSICAL;“保護(hù)屬性”只能是

PAGE_READWRITE。

MEM_PHYSICAL指的是區(qū)域?qū)⑹芪锢泶鎯?chǔ)器的支持。

第二,你要計(jì)算出分配的頁(yè)面數(shù)目PageCount:

利用本文第二節(jié)的GetSystemInfo可以計(jì)算出來(lái)。

第三,分配物理內(nèi)存頁(yè)面:

AllocateUserPhysicalPages (HANDLE?進(jìn)程句柄,SIZE_T?頁(yè)數(shù),ULONG_PTR?頁(yè)面指針數(shù)組)

進(jìn)程句柄可以用GetCurrentProcess()獲得;頁(yè)數(shù)是剛計(jì)算出來(lái)的頁(yè)數(shù)PageCount;頁(yè)面數(shù)組指針unsigned long* Array[PageCount]。

系統(tǒng)會(huì)將分配結(jié)果存進(jìn)這個(gè)數(shù)組。

第四,將物理內(nèi)存與虛擬空間進(jìn)行映射:

MapUserPhysicalPages (PVOID?開(kāi)始地址,SIZE_T?頁(yè)數(shù),ULONG_PTR?頁(yè)面指針數(shù)組)

“開(kāi)始地址”是第一步分配的空間;

這樣的話,虛擬地址就可以使用了。

如果“頁(yè)面指針數(shù)組”是NULL,則取消映射。

第五,釋放物理頁(yè)面

FreeUserPhysicalPages (HANDLE?進(jìn)程句柄,SIZE_T?頁(yè)數(shù),ULONG_PTR?頁(yè)面指針數(shù)組)

這個(gè)除了釋放物理頁(yè)面外,還會(huì)取消物理頁(yè)面的映射。

第六,釋放進(jìn)程空間

VirtualFree (PVOID?開(kāi)始地址,0,MEM_RELEASE)

?

C++程序:

首先,在登錄用戶有了Lock Pages in Memory權(quán)限以后,還需要調(diào)用Windows API激活這個(gè)權(quán)限。

BOOL VirtualMem::LoggedSetLockPagesPrivilege ( HANDLE hProcess,BOOL bEnable)?????????????????????

{

????????????struct?{

????????????????????????DWORD Count;//數(shù)組的個(gè)數(shù)

????????????????????????LUID_AND_ATTRIBUTES Privilege [1];} Info;

????????????HANDLE Token;

????????????//打開(kāi)本進(jìn)程的權(quán)限句柄

????????????BOOL Result = OpenProcessToken ( hProcess,

????????????????????????TOKEN_ADJUST_PRIVILEGES,

????????????????????????& Token);

????????????If?(Result!= TRUE )

????????????{

????????????????????????printf( "Cannot open process token./n" );

????????????????????????return?FALSE;

????????????}

????????????//我們只改變一個(gè)屬性

????????????Info.Count = 1;

????????????//準(zhǔn)備激活

????????????if( bEnable )

????????????????????Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;

????????????else

????????????????????????Info.Privilege[0].Attributes = 0;

????????????//根據(jù)權(quán)限名字找到LGUID

????????????Result = LookupPrivilegeValue ( NULL,

????????????????????????SE_LOCK_MEMORY_NAME,

????????????????????????&(Info.Privilege[0].Luid));

????????????if( Result != TRUE )

????????????{

????????????????????????printf( "Cannot get privilege for %s./n", SE_LOCK_MEMORY_NAME );

????????????????????????return?FALSE;

????????????}

????????????//?激活Lock Pages in Memory權(quán)限

Result = AdjustTokenPrivileges ( Token, FALSE,(PTOKEN_PRIVILEGES) &Info,0, NULL, NULL);

????????????if( Result != TRUE )

????????????{

????????????????????????printf ("Cannot adjust token privileges (%u)/n", GetLastError() );

????????????????????????return?FALSE;

????????????}

????????????else

????????????{

????????????????????????if( GetLastError() != ERROR_SUCCESS )

????????????????????????{

printf ("Cannot enable the SE_LOCK_MEMORY_NAME privilege; ");

????????????????????????????????????printf ("please check the local policy./n");

????????????????????????????????????return?FALSE;

????????????????????????}

????????????}

????????????CloseHandle( Token );

????????????return?TRUE;

}

?

分配100M虛擬空間:

PVOID pVirtual=VirtualAlloc(NULL,100*1024*1024,MEM_RESERVE|MEM_PHYSICAL,PAGE_READWRITE);

????????????if(pVirtual==NULL)

????????????????????????cout<<"沒(méi)有那么大連續(xù)進(jìn)程空間!"<<endl;

?

????????????MEMORYSTATUS memStatusVirtual5;

????????????GlobalMemoryStatus(&memStatusVirtual5);

????????????cout<<"虛擬內(nèi)存分配:"<<endl;

cout<<"減少物理內(nèi)存="<<memStatusVirtual4.dwAvailPhys-memStatusVirtual5.dwAvailPhys<<endl

cout<<"減少可用頁(yè)文件="<<memStatusVirtual4.dwAvailPageFile-memStatusVirtual5.dwAvailPageFile<<endl;

???cout<<"減少可用進(jìn)程空間="

<<memStatusVirtual4.dwAvailVirtual-memStatusVirtual5.dwAvailVirtual<<endl<<endl;

結(jié)果如下:

?

可以看見(jiàn),只分配了進(jìn)程空間,沒(méi)有分配物理內(nèi)存。

?

分配物理內(nèi)存:

ULONG_PTR pages=(ULONG_PTR)100*1024*1024/sysInfo.dwPageSize;

????????????ULONG_PTR *frameArray=new?ULONG_PTR[pages];

????????????//如果沒(méi)激活權(quán)限,是不能調(diào)用這個(gè)方法的,可以調(diào)用,但是返回FALSE

BOOL flag=AllocateUserPhysicalPages(GetCurrentProcess(),

&pages,frameArray);

????????????if(flag==FALSE)

????????????????????????cout<<"分配物理內(nèi)存失敗!"<<endl;

????????????MEMORYSTATUS memStatusVirtual6;

????????????GlobalMemoryStatus(&memStatusVirtual6);

????????????cout<<"物理內(nèi)存分配:"<<endl;

cout<<"減少物理內(nèi)存="<<memStatusVirtual5.dwAvailPhys-memStatusVirtual6.dwAvailPhys<<endl

cout<<"減少可用頁(yè)文件="<<memStatusVirtual5.dwAvailPageFile-memStatusVirtual6.dwAvailPageFile<<endl;

cout<<"減少可用進(jìn)程空間="<<memStatusVirtual5.dwAvailVirtual-memStatusVirtual6.dwAvailVirtual<<endl<<endl;

??結(jié)果如下:

?

分配了物理內(nèi)存,可能分配時(shí)需要進(jìn)程空間管理。

?

物理內(nèi)存映射進(jìn)程空間:

int* pVInt=(int*)pVirtual;

????????????//pVInt[0]=10;這時(shí)候訪問(wèn)會(huì)出錯(cuò)

????????????flag=MapUserPhysicalPages(pVirtual,1,frameArray);

????????????if(flag==FALSE)

????????????????????????cout<<"映射物理內(nèi)存失敗!"<<endl;

????????????MEMORYSTATUS memStatusVirtual7;

????????????GlobalMemoryStatus(&memStatusVirtual7);

????????????cout<<"物理內(nèi)存分配:"<<endl;

cout<<"減少物理內(nèi)存="<<memStatusVirtual6.dwAvailPhys-memStatusVirtual7.dwAvailPhys<<endl

cout<<"減少可用頁(yè)文件="<<memStatusVirtual6.dwAvailPageFile-memStatusVirtual7.dwAvailPageFile<<endl;

cout<<"減少可用進(jìn)程空間="

<<memStatusVirtual6.dwAvailVirtual-memStatusVirtual7.dwAvailVirtual<<endl<<endl;

結(jié)果如下:

?

這個(gè)過(guò)程沒(méi)有損失任何東西。

?

看看第一次映射和第二次映射的值:

pVInt[0]=10;

????????????cout<<"第一次映射值="<<pVInt[0]<<endl;

????????????????????????flag=MapUserPhysicalPages(pVirtual,1,frameArray+1);

????????????if(flag==FALSE)

????????????????????????cout<<"映射物理內(nèi)存失敗!"<<endl;

????????????pVInt[0]=21;

????????????cout<<"第二次映射值="<<pVInt[0]<<endl;

????????????flag=MapUserPhysicalPages(pVirtual,1,frameArray);

????????????if(flag==FALSE)

????????????????????????cout<<"映射物理內(nèi)存失敗!"<<endl;

????????????cout<<"再現(xiàn)第一次映射值="<<pVInt[0]<<endl;

結(jié)果如下:

?

可以看出,第二次映射的值沒(méi)有覆蓋第一次映射的值,也就是說(shuō),用同一個(gè)進(jìn)程空間地址可以取出兩份數(shù)據(jù),這樣的話,相當(dāng)于進(jìn)程的地址空間增大了。

?

總結(jié)

以上是生活随笔為你收集整理的全面介绍Windows内存管理机制及C++内存分配实例(三):虚拟内存的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。