内存状态查询函数

  • 获取当前系统信息:void WINAPI GetSystemInfo(_out LPSYSTEM_INFO lpSystemInfo)
实例代码:
#include <Windows.h>
#include <iostream>
using namespace std;

void main()
{
	SYSTEM_INFO sysInfo;
	GetSystemInfo(&sysInfo);
	cout<<"Page Size: "<<sysInfo.dwPageSize<<'\n'
		<<"Minimum Application Address: "<<sysInfo.lpMinimumApplicationAddress<<'\n'
		<<"Maximum Application Address: "<<sysInfo.lpMaximumApplicationAddress<<'\n'
		<<"Allocation Granularity: "<<sysInfo.dwAllocationGranularity<<endl;
}

执行结果:


总结:该函数是一个win32 API函数,用来获取当前系统信息。函数参数是一个SYSTEM_INFO结构体的长指针,该结构体中与系统内存信息相关的数据成员包括:page size(内存页大小)、Allocation Grannularity(分配粒度)、Minimum Application Address(应用程序可访问到的最低虚拟地址空间)、Maximum Application Address(应用程序可访问到的最高虚拟地址空间)。从执行结果中可以看到,该系统的内存页大小为4KB,分配粒度为64KB,最低应用程序虚拟地址空间是0x00010000(0x00000000~0x0000FFFF这64KB的地址空间是空指针赋值分区,用来捕获空指针访问违规问题,没有任何办法可以让我们分配到这一虚拟地址空间的内存),最高应用程序虚拟地址空间是0x7FFEFFFF,0x00010000~0x7FFEFFFF这一虚拟地址空间正好是用户模式分区。

  • 获取系统当前物理内存和虚拟内存的使用情况:void WINAPI GlobalMemoryInfo(_out LPMEMORYSTATUS lpMemoryStatus)
实例代码:
MEMORYSTATUS stat;

	GlobalMemoryStatus (&stat);
	cout<<"Memory Load: "<<stat.dwMemoryLoad<<"%\n"
		<<"Total physical memory: "<<stat.dwTotalPhys/DIV<<"MB\n"
		<<"Available physical memory: "<<stat.dwAvailPhys/DIV<<"MB\n"
		<<"Total page file: "<<stat.dwTotalPageFile/DIV<<"MB\n"
		<<"Avaliable page file: "<<stat.dwAvailPageFile/DIV<<"MB\n"
		<<"Total virtual memory: "<<stat.dwTotalVirtual/DIV<<"MB\n"
		<<"Avaliable virtual memory: "<<stat.dwAvailVirtual/DIV<<"MB"<<endl;
执行结果:

总结:该函数的参数是一个MEMORYSTATUS结构体的长指针,该结构体的定义如下:
typedef struct _MEMORYSTATUS {
DWORD dwLength; //结构体的长度
DWORD dwMemoryLoad; //物理内存的使用情况,0-100
SIZE_T dwTotalPhys; //物理内存的大小
SIZE_T dwAvailPhys; //当前可用的物理内存大小
SIZE_T dwTotalPageFile; //可调拨的物理存储器的大小:物理内存+页交换文件
SIZE_T dwAvailPageFile; //当前可调拨的物理存储器的大小
SIZE_T dwTotalVirtual; //进程虚拟地址空间中用户模式分区的大小
SIZE_T dwAvailVirtual //进程虚拟地址空间中用户模式分区可用的大小
} MEMORYSTATUS;
从执行结果可以看出,该系统内存使用了59%,总的物理内存为2GB,可用物理内存为835MB,总的可调拨物理存储器的大小为4GB,可用的为1790MB,进程用户模式分区的大小为2047MB,可用空间为2038MB,也就是说该进程只使用了9MB的虚拟内存空间。

在进程里面静态分配一些内存:
//char c[1024*1024];   //Error: stack overflow!
char c[65536];
MEMORYSTATUS stat1;
GlobalMemoryStatus(&stat1);
cout<<"The address of c: "<<&c<<"\n"
	<<"Reduced avaliable physical memory: "<<(stat.dwAvailPhys-stat1.dwAvailPhys)<<"\n"
	<<"Reduced avaliable page file: "<<(stat.dwAvailPageFile-stat1.dwAvailPageFile)<<"\n"
	<<"Reduced avaliable virtual memory: "<<(stat.dwAvailVirtual-stat1.dwAvailVirtual)<<"\n";

执行结果:


可以看到,进程的可用的虚拟地址空间没有减少,并且如果静态分配的局部变量过大,会出现栈溢出错误。原因在于系统在创建每个线程时,会为每个线程预订一定大小的线程栈,并为线程栈调拨一些物理存储页面,局部变量就是放在相应的线程栈里面的。

再来看看在进程中动态分配一些内存的情况:
char *c = new char[stat.dwAvailPhys];
MEMORYSTATUS stat1;
GlobalMemoryStatus(&stat1);
cout<<"The address of c: "<<&c<<"\n"
	<<"Reduced avaliable physical memory: "<<(stat.dwAvailPhys-stat1.dwAvailPhys)<<"\n"
	<<"Reduced avaliable page file: "<<(stat.dwAvailPageFile-stat1.dwAvailPageFile)<<"\n"
	<<"Reduced avaliable virtual memory: "<<(stat.dwAvailVirtual-stat1.dwAvailVirtual)<<"\n";
执行结果:


可以看到,进程的虚拟地址空间减少了。我们知道动态分配的内存是放到堆中的,由此可以知道堆是在进程的虚拟地址空间中的。

  • 分配虚拟地址空间内存:
LPVOID WINAPI VirtualAlloc(
  __in          LPVOID lpAddress,        //分配的起始地址,预订和调拨时会向下取整到分配粒度的整数倍,重置时会向上取整
  __in          SIZE_T dwSize,           //分配的虚拟地址空间大小,预订和调拨时会向上取整到页面大小的整数倍,重置是会向下取整
  __in          DWORD flAllocationType,  //分配类型:MEM_RESERVE(预订)、MEM_COMMIT(调拨)、MEM_RESET(重置)
  __in          DWORD flProtect          //内存保护标识:PAGE_READ、PAGE_READWRITE、PAGE_EXCUTE...
);
  • 释放虚拟地址空间内存:
BOOL WINAPI VirtualFree(
  __in          LPVOID lpAddress,        //要释放的地址空间基地址
  __in          SIZE_T dwSize,           //要释放的地址空间大小
  __in          DWORD dwFreeType         //释放类型:MEM_RELEASE(释放整块区域的虚拟地址空间,释放后类型变为MEM_FREE);MEM_DECOMMIT(解除调拨,释放后类型                                         //变为MEM_RESERVE)
);
  • 查询虚拟地址空间内存使用情况:
SIZE_T WINAPI VirtualQuery(
  __in          LPCVOID lpAddress,                  //要查询的区域起始地址
  __out         PMEMORY_BASIC_INFORMATION lpBuffer, //MEMORY_BASIC_INFORMATION结构体,保存查询结果
  __in          SIZE_T dwLength                     //结构体的大小
);

typedef struct _MEMORY_BASIC_INFORMATION {  
	PVOID BaseAddress;          //页面起始地址
	PVOID AllocationBase;       //页面所在区域起始地址
	DWORD AllocationProtect;    //区域内存保护标识
	SIZE_T RegionSize;          //跟该页面具有相同属性的相邻页面的大小
	DWORD State;                //页面状态:MEM_*:FREE、RESERVE、COMMIT
	DWORD Protect;              //页面内存保护标识:PAGE_*
	DWORD Type                  //页面类型:MEM_*:PRIVATE(进程私有空间)、IMAGE(exe映像)、MAPPED(文件映射)
} MEMORY_BASIC_INFORMATION;
使用实例:

#include <Windows.h>
#include <iostream>
#include <string>
using namespace std;

string GetMemStorageText(DWORD dwStorage) {
	
		string p = "Unknown";
		switch (dwStorage) {
		case MEM_COMMIT:  p = "Commit "; break;
		case MEM_FREE:    p = "Free   "; break;
		case MEM_RESERVE: p = "Reserve"; break;
		case MEM_IMAGE:   p = "Image  "; break;
		case MEM_MAPPED:  p = "Mapped "; break;
		case MEM_PRIVATE: p = "Private"; break;
		}
		return(p);
	}

string GetProtectText(DWORD dwProtect) {

	string p = "Unknown";
	switch (dwProtect & ~(PAGE_GUARD | PAGE_NOCACHE | PAGE_WRITECOMBINE)) {
	case PAGE_READONLY:          p = "-R--"; break;
	case PAGE_READWRITE:         p = "-RW-"; break;
	case PAGE_WRITECOPY:         p = "-RWC"; break;
	case PAGE_EXECUTE:           p = "E---"; break;
	case PAGE_EXECUTE_READ:      p = "ER--"; break;
	case PAGE_EXECUTE_READWRITE: p = "ERW-"; break;
	case PAGE_EXECUTE_WRITECOPY: p = "ERWC"; break;
	case PAGE_NOACCESS:          p = "----"; break;
	}

	return p;
}

void main()
{

	LPVOID baseAddress;
	MEMORY_BASIC_INFORMATION mbi;

	cout<<"-----------------------------------------------------------------------\n";

	baseAddress = VirtualAlloc(NULL, 65536, MEM_RESERVE|MEM_TOP_DOWN, PAGE_READWRITE);
	if (baseAddress==NULL)
	{
		return ;
	}
	cout<<"The baseAddress: "<<baseAddress<<'\n';
	VirtualQuery(baseAddress, &mbi, sizeof mbi);
	cout<<"The region allocation begins at: "<<mbi.AllocationBase<<'\n'
		<<"The base address of region of pages: "<<mbi.BaseAddress<<'\n'
		<<"The memory protect of the region initially allocated: "<<GetProtectText(mbi.AllocationProtect)<<'\n'
		<<"The state of the pages in the region: "<<GetMemStorageText(mbi.State)<<'\n'
		<<"The access protection of the pages in the region: "<<GetProtectText(mbi.Protect)<<'\n'
		<<"The size of the region beginnig at the base address: "<<mbi.RegionSize<<'\n'
		<<"The type of pages in the region: "<<GetMemStorageText(mbi.Type)<<'\n';
	cout<<"-----------------------------------------------------------------------\n";

	baseAddress = VirtualAlloc(baseAddress, 65536, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	if (baseAddress==NULL)
	{
		return ;
	}
	cout<<"The baseAddress: "<<baseAddress<<'\n';
	VirtualQuery(baseAddress, &mbi, sizeof mbi);
	cout<<"The region allocation begins at: "<<mbi.AllocationBase<<'\n'
		<<"The base address of region of pages: "<<mbi.BaseAddress<<'\n'
		<<"The memory protect of the region initially allocated: "<<GetProtectText(mbi.AllocationProtect)<<'\n'
		<<"The state of the pages in the region: "<<GetMemStorageText(mbi.State)<<'\n'
		<<"The access protection of the pages in the region: "<<GetProtectText(mbi.Protect)<<'\n'
		<<"The size of the region beginnig at the base address: "<<mbi.RegionSize<<'\n'
		<<"The type of pages in the region: "<<GetMemStorageText(mbi.Type)<<'\n';
	cout<<"-----------------------------------------------------------------------\n";

	baseAddress = VirtualAlloc(baseAddress, 1024+4096, MEM_RESET, PAGE_EXECUTE_READWRITE);
	if (baseAddress==NULL)
	{
		DWORD error = GetLastError();
		cout<<error<<endl;
		return ;
	}
	cout<<"The baseAddress: "<<baseAddress<<'\n';
	VirtualQuery(baseAddress, &mbi, sizeof mbi);
	cout<<"The region allocation begins at: "<<mbi.AllocationBase<<'\n'
		<<"The base address of region of pages: "<<mbi.BaseAddress<<'\n'
		<<"The memory protect of the region initially allocated: "<<GetProtectText(mbi.AllocationProtect)<<'\n'
		<<"The state of the pages in the region: "<<GetMemStorageText(mbi.State)<<'\n'
		<<"The access protection of the pages in the region: "<<GetProtectText(mbi.Protect)<<'\n'
		<<"The size of the region beginnig at the base address: "<<mbi.RegionSize<<'\n'
		<<"The type of pages in the region: "<<GetMemStorageText(mbi.Type)<<'\n';
	cout<<"-----------------------------------------------------------------------\n";

	if(!VirtualFree(baseAddress, 65536, MEM_DECOMMIT))
		return;
	cout<<"The baseAddress: "<<baseAddress<<'\n';
	VirtualQuery(baseAddress, &mbi, sizeof mbi);
	cout<<"The region allocation begins at: "<<mbi.AllocationBase<<'\n'
		<<"The base address of region of pages: "<<mbi.BaseAddress<<'\n'
		<<"The memory protect of the region initially allocated: "<<GetProtectText(mbi.AllocationProtect)<<'\n'
		<<"The state of the pages in the region: "<<GetMemStorageText(mbi.State)<<'\n'
		<<"The access protection of the pages in the region: "<<GetProtectText(mbi.Protect)<<'\n'
		<<"The size of the region beginnig at the base address: "<<mbi.RegionSize<<'\n'
		<<"The type of pages in the region: "<<GetMemStorageText(mbi.Type)<<'\n';
	cout<<"-----------------------------------------------------------------------\n";

	if(!VirtualFree(baseAddress, 0, MEM_RELEASE))
		return;
	cout<<"The baseAddress: "<<baseAddress<<'\n';
	VirtualQuery(baseAddress, &mbi, sizeof mbi);
	cout<<"The region allocation begins at: "<<mbi.AllocationBase<<'\n'
		<<"The base address of region of pages: "<<mbi.BaseAddress<<'\n'
		<<"The memory protect of the region initially allocated: "<<GetProtectText(mbi.AllocationProtect)<<'\n'
		<<"The state of the pages in the region: "<<GetMemStorageText(mbi.State)<<'\n'
		<<"The access protection of the pages in the region: "<<GetProtectText(mbi.Protect)<<'\n'
		<<"The size of the region beginnig at the base address: "<<mbi.RegionSize<<'\n'
		<<"The type of pages in the region: "<<GetMemStorageText(mbi.Type)<<'\n';
	cout<<"-----------------------------------------------------------------------\n";

	char a[4097];
	cout<<"The baseAddress: "<<&a<<'\n';
	VirtualQuery(a, &mbi, sizeof mbi);
	cout<<"The region allocation begins at: "<<mbi.AllocationBase<<'\n'
		<<"The base address of region of pages: "<<mbi.BaseAddress<<'\n'
		<<"The memory protect of the region initially allocated: "<<GetProtectText(mbi.AllocationProtect)<<'\n'
		<<"The state of the pages in the region: "<<GetMemStorageText(mbi.State)<<'\n'
		<<"The access protection of the pages in the region: "<<GetProtectText(mbi.Protect)<<'\n'
		<<"The size of the region beginnig at the base address: "<<mbi.RegionSize<<'\n'
		<<"The type of pages in the region: "<<GetMemStorageText(mbi.Type)<<'\n';
	cout<<"-----------------------------------------------------------------------\n";

	char b[900000];
	cout<<"The baseAddress: "<<&b<<'\n';
	VirtualQuery(b, &mbi, sizeof mbi);
	cout<<"The region allocation begins at: "<<mbi.AllocationBase<<'\n'
		<<"The base address of region of pages: "<<mbi.BaseAddress<<'\n'
		<<"The memory protect of the region initially allocated: "<<GetProtectText(mbi.AllocationProtect)<<'\n'
		<<"The state of the pages in the region: "<<GetMemStorageText(mbi.State)<<'\n'
		<<"The access protection of the pages in the region: "<<GetProtectText(mbi.Protect)<<'\n'
		<<"The size of the region beginnig at the base address: "<<mbi.RegionSize<<'\n'
		<<"The type of pages in the region: "<<GetMemStorageText(mbi.Type)<<'\n';
	cout<<"-----------------------------------------------------------------------\n";

	char *c = new char[900000];
	cout<<"The baseAddress: "<<&c<<'\n';
	VirtualQuery(c, &mbi, sizeof mbi);
	cout<<"The region allocation begins at: "<<mbi.AllocationBase<<'\n'
		<<"The base address of region of pages: "<<mbi.BaseAddress<<'\n'
		<<"The memory protect of the region initially allocated: "<<GetProtectText(mbi.AllocationProtect)<<'\n'
		<<"The state of the pages in the region: "<<GetMemStorageText(mbi.State)<<'\n'
		<<"The access protection of the pages in the region: "<<GetProtectText(mbi.Protect)<<'\n'
		<<"The size of the region beginnig at the base address: "<<mbi.RegionSize<<'\n'
		<<"The type of pages in the region: "<<GetMemStorageText(mbi.Type)<<'\n';
	cout<<"-----------------------------------------------------------------------\n";

	char *d = new char[900000];
	cout<<"The baseAddress: "<<&d<<'\n';
	VirtualQuery(d, &mbi, sizeof mbi);
	cout<<"The region allocation begins at: "<<mbi.AllocationBase<<'\n'
		<<"The base address of region of pages: "<<mbi.BaseAddress<<'\n'
		<<"The memory protect of the region initially allocated: "<<GetProtectText(mbi.AllocationProtect)<<'\n'
		<<"The state of the pages in the region: "<<GetMemStorageText(mbi.State)<<'\n'
		<<"The access protection of the pages in the region: "<<GetProtectText(mbi.Protect)<<'\n'
		<<"The size of the region beginnig at the base address: "<<mbi.RegionSize<<'\n'
		<<"The type of pages in the region: "<<GetMemStorageText(mbi.Type)<<'\n';
	cout<<"-----------------------------------------------------------------------\n";
}


 

执行结果:



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章