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错误。