《Windows核心编程》の内存操作和内存信息管理

=======================内存操作函数========================

1)复制内存使用函数CopyMemory:(注意:源内存区域与目的地址区域不能重叠)

void CopyMemory(

  __in  PVOID Destination, //目的地址

  __in  const VOID *Source, //源地址

  __in  SIZE_T Length //要复制的数据的字节大小,注意Destination必须足够大来容纳Length长的数据

);

下面的实例是更安全地使用CopyMemory的方法:

#include <windows.h>

#include <tchar.h>

#include <stdio.h>

 

#define BUFFER_SIZE 1024

#define COPY_SIZE 512

 

/*

* ASCECopyMemory--A Wrapper for CopyMemory

* buf--destination buffer

* pbData--source buffer

* cbData--size of block to copy, in bytes

* bufsize--size of the destination buffer

*/

void ASCECopyMemory(TCHAR *buf, TCHAR *pbData, SIZE_T cbData, SIZE_T bufsize)

{

    CopyMemory(buf, pbData, min(cbData, bufsize));    

}

 

int main()

{

    TCHAR buf[BUFFER_SIZE] = TEXT("This is the destination");

    TCHAR pbData[BUFFER_SIZE] = TEXT("This is the source");

   

    ASCECopyMemory(buf, pbData, COPY_SIZE*sizeof(TCHAR), BUFFER_SIZE*sizeof(TCHAR));

   

    _tprintf(TEXT("Destination buffer contents : %s/n"), buf);

   

    system("pause");

    return 0;   

}

 

2)填充内存使用函数FillMemory

void FillMemory(

  [out]  PVOID Destination, //需要填充的内存地址

  [in]   SIZE_T Length, //需要填充的字节大小

  [in]   BYTE Fill //需要填充的值

);

 

3)复制内存还可以使用函数MoveMemory:(注意:源内存区域可以和目的内存区域重叠)

void MoveMemory(

  __in  PVOID Destination, //目的地址

  __in  const VOID *Source, //源地址

  __in  SIZE_T Length //复制的数据的字节大小,注意Destination必须足够大来容纳Length长的数据

);

 

下面的实例是更安全地使用MoveMemory的方法:

#include <windows.h>

#include <tchar.h>

#include <stdio.h>

 

#define BUFFER_SIZE 1024

#define COPY_SIZE 512

 

/*

* ASCEMoveMemory--A Wrapper for MoveMemory

* buf--destination buffer

* pbData--source buffer

* cbData--size of block to copy, in bytes

*/

void ASCEMoveMemory(TCHAR *buf, TCHAR *pbData, SIZE_T cbData)

{

    MoveMemory(buf, pbData, min(cbData, strlen(buf)));

}

 

int main()

{

    TCHAR buf[BUFFER_SIZE] = TEXT("This is the destination");

    TCHAR pbData[BUFFER_SIZE] = TEXT("This is the source");

   

    ASCEMoveMemory(buf, pbData, COPY_SIZE*sizeof(TCHAR));

   

    _tprintf(TEXT("Destination buffer contents : %s/n"), buf);

   

    system("pause");

    return 0;   

}

 

4)将指定内存清零使用函数ZeroMemory

void ZeroMemory(

  [in]  PVOID Destination, //要清零的内存地址

  [in]  SIZE_T Length //Destination内存区域的字节大小

);

在有些情况下,为了避免编译器优化带来的副作用,我们可以使用SecureZeroMemory函数:

PVOID SecureZeroMemory(

  __in  PVOID ptr, //要清零的内存地址

  __in  SIZE_T cnt //内存区域的字节大小

);

 

下面的代码片段最好使用SecureZeroMemory,而不是ZeroMemory

WCHAR szPassword[MAX_PATH];

//Retrieve the password

if(GetPasswordFromUser(szPassword, MAX_PATH))

         UsePassword(szPassword);

//Clear the password from memory

SecureZeroMemory(szPassword, sizeof(szPassword));

上面的代码如果使用ZeroMemory,那么编译器可能会优化该函数的调用,使得szPassword中的密码一直留着应用程序的堆栈中,而不是清零,这显然会造成安全问题。

 

====================获得当前系统内存使用情况====================

当前系统内存使用情况包括物理内存、可使用的物理内存、总虚拟内存、可用虚拟内存、磁盘上的页面缓存文件大小、可使用的缓存文件大小等。

详见:Windows核心编程》---获得内存的当前状态のGlobalMemoryStatusEx

http://blog.csdn.net/ACE1985/archive/2010/07/24/5761972.aspx 

 

 

======================判断内存指针可用性======================

判断内存指针的可用性,是通过判断指针所指向的虚拟内存页面的状态和属性来实现的。Windows提供了相关的API。相同的功能也可以通过获取虚拟内存页面属性来判断。

1IsBadCodePtr

判断调用进程是否拥有对指定地址内存的读操作权限,函数原型如下:

BOOL WINAPI IsBadCodePtr(

  __in  FARPROC lpfn //指定的内存地址

);

返回值表示当前进程是否拥有对该地址内存的读取权限。

 

2IsBadReadPtr

判断调用进程是否拥有对指定地址段内存的读操作权限,函数原型如下:

BOOL WINAPI IsBadReadPtr(

  __in  const VOID *lp, //指定起始内存地址

  __in  UINT_PTR ucb //从起始内存地址开始的内存块长度

);

返回值表示当前进程是否拥有对该段地址内存块的读取权限。

 

3IsBadStringPtr

判断调用进程是否拥有对指定字符串指针的读取权限,函数原型如下:

BOOL WINAPI IsBadStringPtr(

  __in  LPCTSTR lpsz, //指向字符串的指针

  __in  UINT_PTR ucchMax //读取字符串的最大长度

);

返回值表示当前进程是否拥有字符串指针指向的字符串的读取权限。

 

4IsBadWritePtr

BOOL WINAPI IsBadWritePtr(

  __in  LPVOID lp, //指向起始内存地址

  __in  UINT_PTR ucb //从起始内存地址开始的内存块长度

);

返回值表示当前进程是否拥有该段地址内存块的写入权限。

 

 

 

你可能感兴趣的:(编程,windows,buffer,wrapper,编译器,winapi)