内存状态查询函数
- 获取当前系统信息: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 //进程虚拟地址空间中用户模式分区可用的大小
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"; }
执行结果: