VirtualProtect函数用于改变内存页面的存取属性 :
#define PAGE_NOACCESS 0x01
#define PAGE_READONLY 0x02
#define PAGE_READWRITE 0x04
#define PAGE_WRITECOPY 0x08
#define PAGE_EXECUTE 0x10
#define PAGE_EXECUTE_READ 0x20
#define PAGE_EXECUTE_READWRITE 0x40
#define PAGE_EXECUTE_WRITECOPY 0x80
#define PAGE_GUARD 0x100
#define PAGE_NOCACHE 0x200
#define PAGE_WRITECOMBINE 0x400
应用这个函数本来是用于内存池越界诊断的,但是很不幸的,内存池挂掉了。
这里写了一段测试code,VS2005编译,这段代码会crash:
BYTE* pTest = new BYTE[1024];
DWORD dwOldState = 0;
VirtualProtect(pTest,1,PAGE_READONLY,&dwOldState);
BYTE* p=new BYTE[1];
p[0]= 0xff;
代码crash在:
BYTE* p=new BYTE[1];
原因:
VirtualProtect的粒度是一张内存页面,而windows的页面大小为4K,所以
VirtualProtect(pTest,1,PAGE_READONLY,&dwOldState);
会使得pTest所在内存的页面被修改为readonly,而pTest和p两者内存地址比较靠近,在同一张页面内,所以对p的写入会导致crash错误。