=======================内存操作函数========================
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提供了相关的API。相同的功能也可以通过获取虚拟内存页面属性来判断。
1)IsBadCodePtr:
判断调用进程是否拥有对指定地址内存的读操作权限,函数原型如下:
BOOL WINAPI IsBadCodePtr(
__in FARPROC lpfn //指定的内存地址
);
返回值表示当前进程是否拥有对该地址内存的读取权限。
2)IsBadReadPtr:
判断调用进程是否拥有对指定地址段内存的读操作权限,函数原型如下:
BOOL WINAPI IsBadReadPtr(
__in const VOID *lp, //指定起始内存地址
__in UINT_PTR ucb //从起始内存地址开始的内存块长度
);
返回值表示当前进程是否拥有对该段地址内存块的读取权限。
3)IsBadStringPtr:
判断调用进程是否拥有对指定字符串指针的读取权限,函数原型如下:
BOOL WINAPI IsBadStringPtr(
__in LPCTSTR lpsz, //指向字符串的指针
__in UINT_PTR ucchMax //读取字符串的最大长度
);
返回值表示当前进程是否拥有字符串指针指向的字符串的读取权限。
4)IsBadWritePtr:
BOOL WINAPI IsBadWritePtr(
__in LPVOID lp, //指向起始内存地址
__in UINT_PTR ucb //从起始内存地址开始的内存块长度
);
返回值表示当前进程是否拥有该段地址内存块的写入权限。