原文出处:http://www.devdiv.net/thread-15649-1-1.html(转载时请注明)
原理是申请内存时,多申请一些,并把后面的保护起来。
这样,当程序访问越界时,就会报异常,并在当前调用栈停下来,让我们可以跟踪凶案现场。
增加以下实现与宏定义:
inline
void* devdiv_malloc_protected(size_t size)
{
int page_num = (int) (size / 0x1000 + 1);
size_t offset = page_num * 0x1000 - size;
void* p = ::VirtualAlloc(NULL, page_num*0x1000+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (NULL == p)
{
// ASSERT(FALSE);
return NULL; // 内存用尽
}
void* pchecker = (char*)p + page_num * 0x1000;
DWORD old_value;
::VirtualProtect(pchecker, 0x1000, PAGE_NOACCESS, &old_value);
return (char*)p + offset;
}
inline
void devdiv_free_protected(void* p)
{
//找到VirtualAlloc时候的起始地址
p = (char*)p - (size_t)p % 0x1000;
::VirtualFree(p, 0, MEM_RELEASE);
}
inline
void* __cdecl operator new(unsigned int s, int)
{
return devdiv_malloc_protected(s);
}
// {{ 如果把以下注释掉,则异常出现在不该出现的地方。
#ifdef _DEBUG
inline
void __cdecl operator delete[](void* pvMem)
{
devdiv_free_protected(pvMem);
}
#define malloc devdiv_malloc_protected
#define free devdiv_free_protected
#define new new(1)
#endif
// }}
测试代码:
void main()
{
char* p = (char*)malloc(5);
char* p2 = new char[5];
strcpy(p, "devdiv"); // 我希望这里异常。而不是把隐患留着,以后出现在不该出现的莫名其妙的地方。
strcpy(p2, "devdiv"); // 我希望这里异常
free(p);
delete[] p2;
}
这样用的缺点是,每次分配内存,都会比较耗。因为设置windows的内存保护属性是以页(默认是0x1000 byte)为单位的。但一般只定义为DEBUG版时用。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/frankywu2008/archive/2010/03/05/5347193.aspx