#ifndef _CHECKMEMOVERFLOW_H_
#define _CHECKMEMOVERFLOW_H_
#define CHECK_MEM_OVERFLOW
#ifdef CHECK_MEM_OVERFLOW
//操作系統(tǒng)內(nèi)存分配粒度為頁面(4K)
#define PAGE_SIZE 4096
#define PLATFORM_WIN32
#ifdef PLATFORM_WIN32
#include <stdlib.h>
#include <windows.h>
/*
* oooooooo
ooooo | *******
*
(*)acture memory pages | protect page
*/
inline void * operator new (size_t size)
{
size_t page_num = (size_t)(size / PAGE_SIZE);
size_t offset = 0;
if(0 != (size % PAGE_SIZE))
{
page_num++;
offset = PAGE_SIZE - size % PAGE_SIZE;
}
void *p = VirtualAlloc(NULL,page_num*PAGE_SIZE+1,MEM_COMMIT,PAGE_READWRITE);
void *pchecker = (char*)p + page_num*PAGE_SIZE;
DWORD old_value;
VirtualProtect(pchecker,PAGE_SIZE,PAGE_NOACCESS,&old_value);
return (char *)p + offset;
}
inline void operator delete(void *p)
{
void* address = (char *)p - (size_t)(p) % PAGE_SIZE;
VirtualFree(address,0,MEM_RELEASE);
}
#else
#include <stdlib.h>
#include <sys/mman.h>
#include <stdio.h>
/*
* ********* |oooooooooooooooo
ooooo | ***********
* size page |
(*)acture memory pages | protect page
*/
//gcc : connot be inline
void * operator new (size_t size)
{
//calc page num and offset
int page_num = (int)(size / PAGE_SIZE + 1);
size_t offset = page_num * PAGE_SIZE - size;
//alloc memory pages
void *p = mmap(NULL,page_num*PAGE_SIZE+2,PROT_READ|PROT_WRITE,MAP_PRIVATE | MAP_ANON, -1, 0);
//saved page num
size_t* pSize = (size_t*)((char*)p+PAGE_SIZE-sizeof(size_t));
*pSize = page_num+2;
mprotect(p, PAGE_SIZE, PROT_NONE);
//set memory overflow protect page
void *pchecker = (char*)p + page_num*PAGE_SIZE;
mprotect(pchecker, PAGE_SIZE, PROT_NONE);
return (char *)p + offset;
}
void operator delete(void *p)
{
//calc acture memory page start address
void* address = (char *)p - (size_t)p % PAGE_SIZE;
mprotect((char*)address-PAGE_SIZE, PAGE_SIZE, PROT_READ);
size_t pagenum = (size_t)*((char*)address-sizeof(size_t));
munmap((char*)address-PAGE_SIZE, pagenum*PAGE_SIZE);
}
#endif
#endif
//#define TEST_OVERFLOW
#ifdef TEST_OVERFLOW
#include <stdio.h>
int main(int argc,char *argv[])
{
printf("test start
\n");
char * a = new char[12340];
printf("%c\n",a[12340]); //程序運行到這里將出現(xiàn)debug中斷
delete[] a;
printf("test done
\n");
return 0;
}
#endif
#endif
#define _CHECKMEMOVERFLOW_H_
#define CHECK_MEM_OVERFLOW
#ifdef CHECK_MEM_OVERFLOW
//操作系統(tǒng)內(nèi)存分配粒度為頁面(4K)
#define PAGE_SIZE 4096
#define PLATFORM_WIN32
#ifdef PLATFORM_WIN32
#include <stdlib.h>
#include <windows.h>
/*
* oooooooo
ooooo | ********
(*)acture memory pages | protect page*/
inline void * operator new (size_t size)
{
size_t page_num = (size_t)(size / PAGE_SIZE);
size_t offset = 0;
if(0 != (size % PAGE_SIZE))
{
page_num++;
offset = PAGE_SIZE - size % PAGE_SIZE;
}
void *p = VirtualAlloc(NULL,page_num*PAGE_SIZE+1,MEM_COMMIT,PAGE_READWRITE);
void *pchecker = (char*)p + page_num*PAGE_SIZE;
DWORD old_value;
VirtualProtect(pchecker,PAGE_SIZE,PAGE_NOACCESS,&old_value);
return (char *)p + offset;
}
inline void operator delete(void *p)
{
void* address = (char *)p - (size_t)(p) % PAGE_SIZE;
VirtualFree(address,0,MEM_RELEASE);
}
#else
#include <stdlib.h>
#include <sys/mman.h>
#include <stdio.h>
/*
* ********* |oooooooooooooooo
ooooo | ************ size page |
(*)acture memory pages | protect page*/
//gcc : connot be inline
void * operator new (size_t size)
{
//calc page num and offset
int page_num = (int)(size / PAGE_SIZE + 1);
size_t offset = page_num * PAGE_SIZE - size;
//alloc memory pages
void *p = mmap(NULL,page_num*PAGE_SIZE+2,PROT_READ|PROT_WRITE,MAP_PRIVATE | MAP_ANON, -1, 0);
//saved page num
size_t* pSize = (size_t*)((char*)p+PAGE_SIZE-sizeof(size_t));
*pSize = page_num+2;
mprotect(p, PAGE_SIZE, PROT_NONE);
//set memory overflow protect page
void *pchecker = (char*)p + page_num*PAGE_SIZE;
mprotect(pchecker, PAGE_SIZE, PROT_NONE);
return (char *)p + offset;
}
void operator delete(void *p)
{
//calc acture memory page start address
void* address = (char *)p - (size_t)p % PAGE_SIZE;
mprotect((char*)address-PAGE_SIZE, PAGE_SIZE, PROT_READ);
size_t pagenum = (size_t)*((char*)address-sizeof(size_t));
munmap((char*)address-PAGE_SIZE, pagenum*PAGE_SIZE);
}
#endif
#endif
//#define TEST_OVERFLOW
#ifdef TEST_OVERFLOW
#include <stdio.h>
int main(int argc,char *argv[])
{
printf("test start
\n");char * a = new char[12340];
printf("%c\n",a[12340]); //程序運行到這里將出現(xiàn)debug中斷
delete[] a;
printf("test done
\n");return 0;
}
#endif
#endif
原理:
1,重載全局new/delete,接管內(nèi)存申請/釋放;
2.a,在windows下,頁面最小分配單位為4K,調(diào)用VirtualAlloc分配內(nèi)存,并在最后一個頁面后面添加一個“哨兵”頁面,頁面屬性為NOACCESS,讀寫該頁面均crash;
2.b,在linux下,原理同上,但必須在申請的內(nèi)存前面多申請一個頁面保存申請的頁面數(shù);
注意:
只能在C++中使用,windows/mac下測試通過。
使用方法:
只要include這個頭文件即可,且內(nèi)存必須是new出來的,而非malloc的。
參考:
1,http://www.wangchao.net.cn/bbsdetail_65784.html
2,http://blog.csdn.net/cjfeii/article/details/9122279

