內存狀態查詢函數

  • 獲取當前系統信息: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";
}


 

執行結果:



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