windows 内存管理api学习笔记

为什么使用虚拟内存

虚拟内存最适合用来管理大型对象或数据结构。

比如说,电子表格程序,有很多单元格,但是也许大多数的单元格是没有数据的,用不着分配空间。也许,你会想到用动态链表,但是访问又没有数组快。定义二维数组,就会浪费很多空间。

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


分配虚拟内存

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


Windows内存管理API

VirtualAlloc

在调用进程的虚拟地址空间中保留、提交或更改页面区域的状态。此函数分配的内存会自动初始化为零。
参数

[in, optional] LPVOID lpAddress,        //开始地址
[in]           SIZE_T dwSize,           //大小
[in]           DWORD  flAllocationType, //类型
[in]           DWORD  flProtect         //保护属性
  • lpAddress:要分配的区域的起始地址。
    一般情况下,你不需要指定“开始地址”,因为你不知道进程的那段空间是不是已经被占用了;所以你可以用NULL。
  • dwSize:区域的大小,以字节为单位。
  • flAllocationType:
    “类型”有
    MEM_RESERVE(保留)保留区域不占用任何物理存储。
    MEM_RELEASE(释放)
    MEM_COMMIT(提交)为指定的保留内存页面分配内存费用
    如果你要保留的是长久不会释放的内存区,就保留在较高的空间区域,这样不会产生碎片。用这个类型标志可以达到:
    MEM_RESERVE|MEM_TOP_DOWN。
  • flProtect:要分配的页面区域的内存保护。

返回值
如果函数成功,则返回值是页面分配区域的基地址。

如果函数失败,则返回值为NULL。要获取扩展错误信息,请调用GetLastError。

VirtualProtect

更改对调用进程虚拟地址空间中已提交页面区域的保护。
参数

[in]  LPVOID lpAddress,
[in]  SIZE_T dwSize,
[in]  DWORD  flNewProtect,  //新属性
[out] PDWORD lpflOldProtect //旧属性

返回值
如果函数成功,则返回值非零。

如果函数失败,则返回值为零。要获取扩展错误信息,请调用 GetLastError。

VirtualFree

调用进程的虚拟地址空间内释放、取消提交或释放和取消提交页面区域。
参数

[in] LPVOID lpAddress,  //指向要释放的页面区域的基地址的指针。
[in] SIZE_T dwSize,     //要释放的内存区域的大小,以字节为单位。
[in] DWORD  dwFreeType  //释放操作的类型。
  • dwFreeType类型
    MEM_DECOMMIT 取消提交页面的指定区域。操作后,页面处于保留状态。
    MEM_RELEASE 释放指定的页面区域或占位符(对于占位符,地址空间被释放并可用于其他分配)。此操作后,页面处于空闲状态。

返回值
如果函数成功,则返回值非零。

如果函数失败,则返回值为 0(零)。要获取扩展错误信息,请调用 GetLastError


C++代码

自定义内存状况输出函数

void printMemStatus()
{
    MEMORYSTATUS memStatusVirtual;
    GlobalMemoryStatus(&memStatusVirtual);
    cout << "dwAvailPhys :"<<memStatusVirtual.dwAvailPhys/1024/1024<<"MB"<<endl;
    cout << "dwAvailPageFile :"<<memStatusVirtual.dwAvailPageFile/1024/1024<<"MB"<<endl;
    cout << "dwAvailVirtual :"<<memStatusVirtual.dwAvailVirtual/1024/1024<<"MB"<<endl;
}

保留空间

//输出内存保留前情况
printMemStatus();

//保留512mb的空间
LPVOID pV=VirtualAlloc(NULL,512*1024*1024,MEM_RESERVE|MEM_TOP_DOWN,PAGE_READWRITE); 
if(pV==NULL){
    cout<<"VirtualAlloc MEM_RESERVE failed."<<endl; 
    return 0; 
}

cout<<"******************************"<<endl;
cout<<"After VirtualAlloc MEM_RESERVE"<<endl;
cout<<"******************************"<<endl;
//输出保留后内存情况
printMemStatus();

在这里插入图片描述
dwAvailVirtual 进程可用虚拟内存减少了512mb

提交

//提交 128mb 空间 
LPVOID pP=VirtualAlloc(pV,128*1024*1024,MEM_COMMIT,PAGE_READWRITE);    
if(pP==NULL){
    cout<<"VirtualAlloc MEM_COMMIT failed."<<endl;
    return 0;
}
cout<<"******************************"<<endl;
cout<<"After VirtualAlloc MEM_COMMIT"<<endl;
cout<<"******************************"<<endl;
printMemStatus();

在这里插入图片描述
dwAvailPhys 实际物理内存减少了128mb
修改页保护属性

DWORD protect;
VirtualProtect(pV, 1024*4, PAGE_READONLY,&protect) ;
int * iP=(int*)pV;
iP[1023] = 1; //报错,在这一页之中 
iP[1024] = 1; //不报错 

释放

//只释放物理内存
VirtualFree((int*)pV,100*1024*1024,MEM_DECOMMIT);
cout<<"******************************"<<endl;
cout<<"After VirtualFree MEM_DECOMMIT"<<endl;
cout<<"******************************"<<endl;
printMemStatus(); 
//释放全部空间
VirtualFree(pV,0,MEM_RELEASE); 
cout<<"******************************"<<endl;
cout<<"After VirtualFree MEM_RELEASE"<<endl;
cout<<"******************************"<<endl;
printMemStatus(); 

完整代码

#include <cstdio>
#include <memoryapi.h>
#include <Windows.h>
#include <winbase.h> 
#include <iostream> 
using namespace std;
void printMemStatus()
{
	MEMORYSTATUS memStatusVirtual;
	GlobalMemoryStatus(&memStatusVirtual);
	cout << "dwAvailPhys :"<<memStatusVirtual.dwAvailPhys/1024/1024<<"MB"<<endl;
    cout << "dwAvailPageFile :"<<memStatusVirtual.dwAvailPageFile/1024/1024<<"MB"<<endl;
    cout << "dwAvailVirtual :"<<memStatusVirtual.dwAvailVirtual/1024/1024<<"MB"<<endl;
}
int main()
{
	printMemStatus();
	//保留512mb的空间
	LPVOID pV=VirtualAlloc(NULL,512*1024*1024,MEM_RESERVE|MEM_TOP_DOWN,PAGE_READWRITE); 
    if(pV==NULL){
    	cout<<"VirtualAlloc MEM_RESERVE failed."<<endl; 
    	return 0; 
	}
    cout<<"******************************"<<endl;
    cout<<"After VirtualAlloc MEM_RESERVE"<<endl;
    cout<<"******************************"<<endl;
    printMemStatus();

	//提交 128mb 空间 
	LPVOID pP=VirtualAlloc(pV,128*1024*1024,MEM_COMMIT,PAGE_READWRITE);    
    if(pP==NULL){
    	cout<<"VirtualAlloc MEM_COMMIT failed."<<endl;
    	return 0;
	}
	cout<<"******************************"<<endl;
    cout<<"After VirtualAlloc MEM_COMMIT"<<endl;
    cout<<"******************************"<<endl;
	printMemStatus();
    	
	//更改页面保护属性 
    DWORD protect;
    VirtualProtect(pV, 1024*4, PAGE_READONLY,&protect) ;
    int * iP=(int*)pV;
    //iP[1023] = 1; //报错,在这一页之中 
    iP[1024] = 1; //不报错 
    
    
    //只释放100mb物理内存
    VirtualFree((int*)pV,100*1024*1024,MEM_DECOMMIT);
    cout<<"******************************"<<endl;
    cout<<"After VirtualFree MEM_DECOMMIT"<<endl;
    cout<<"******************************"<<endl;
    printMemStatus(); 
    //释放全部空间
	VirtualFree(pV,0,MEM_RELEASE);
	cout<<"******************************"<<endl;
    cout<<"After VirtualFree MEM_RELEASE"<<endl;
    cout<<"******************************"<<endl;
    printMemStatus(); 
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_46827210/article/details/121439579