这段代码首先调拨了一块存储器,然后将这块内存的前4个字节标记为可以被重置。但是重置存储器的操作会调用失败。第二个VirtualAlloc会返回NULL。GetLastError会返回ERROR_INVALID_ADDRESS。

  这是因为在传入MEM_RESET给VirtualAlloc时,函数会把基地址向下取整到页面大小的整数倍。(其他标志时都是向上去整,此处要注意。)其目的是确保在同一页面中还有其他重要数据的情况下,不会把它们丢弃。前面的例子,向下去整到页面整数倍是0,这是没有意义的。也是说我们重置的页面必须是一个或几个完整的页面。不足一页的为了保护数据不将它们设为可重置。

  还要注意MEM_RESET不能和其他标志一起使用,它不合群,只能单独使用。否则调用会失败。

  VirtualQuery函数。

  VirtualQuery可以用来查询与地址空间有关的特定信息。比如大小,存储器类型及保护属性。


DWORD VirtualQuery(

     LPCVOID pvAddress,

     PMEMORY_BASIC_INFORMATION pmbi,

     DWORD dwLength);
 


  pvAddress指定需要查询的虚拟内存地址。

  dwLength指定MEMORY_BASIC_INFORMATION结构大小。

  pmbi返回MEM_BASIC_INFORMATION结构地址。该地址定义如下:


typedef struct _MEMORY_BASIC_INFORMATION

{

    PVOID BaseAddress;//等于pvAddress向下取整到页面大小。

    PVOID AllocationBase;//区域基地址。

    DWORD AllocationProtect;//预定区域时的保护属性。

    SIZE_T RegionSize;//区域大小。以字节为单位。以BaseAddress为起始地址。

    DWORD State;//区域页面的状态。

    DWORD Protect;//保护属性

    DWORD Type;//

}MEMORY_BASIC_INFORMATION,*PMEMORY_BASIC_INFROMATION;
 


  VirtualQueryEx与VirtualQuery的区别是它可以传入一个进程句柄。也意味着它可以查询其他进程地址空间的信息。

  GlobalMemoryStatus可以用来取得当前内存状态的动态信息:


VOID GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer);


  MEMORYSTATUS结构定义如下:


typedef struct _MEMORYSTATUS

 {

   DWORD dwLenght;//此结构大小。调用函数前必须初始化。

   DWORD dwMemoryLoad;//

   SIZE_T dwTotalPhys;

   SIZE_T dwAvailablePhys;

   SIZE_T dwTotalPageFile;

   SIZE_T dwAvailablePageFile;

   SIZE_T dwTotalVirtual;

   SIZE_T dwAvailVirtual;

  }MEMORYSTATUS,*LPMEMORYSTATUS;
 


  dwMemoryLoad成员告诉我们内存管理系统有多忙,它可以是0-100之间的任何值。实际中,这个值没有什么用处。

  dwTotalPhys成员表示物理内存总量。

  dwAvailPhys成员表示可分配的内存总理。都是以字节为单位。

  dwTotalPageFile表示硬盘页交换文件多能存放多少字节的数据。

  dwTotalVirtual表示地址空间中各进程私有的那部分字节数。比2G少128k.从0x00000000-0x0000FFFF(空指针赋值分区)和从0x7FFF0000-0x7FFFFFFF(64KB进入分区)这两个分区应用程序不能访问。

  dwAvailVirtual是一个与进程有关的成员。它表示还有多少闲置的地址空间可以被使用。也说dwTotalVirtual-进程预定的地址空间等于dwAvailVirtual。