一段用于监测C++内存越界的代码 , VC++,GCC编译测试通过

#ifndef _CHECKMEMOVERFLOW_H_
#define _CHECKMEMOVERFLOW_H_

#define CHECK_MEM_OVERFLOW

#ifdef CHECK_MEM_OVERFLOW
//操作系统内存分配粒度为页面(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]); //程序运行到这里将出现debug中断
	delete[] a;
    printf("test done...\n");
	return 0;
}
#endif
#endif

原理:

1,重载全局new/delete,接管内存申请/释放;

2.a,在windows下,页面最小分配单位为4K,调用VirtualAlloc分配内存,并在最后一个页面后面添加一个“哨兵”页面,页面属性为NOACCESS,读写该页面均crash;

2.b,在linux下,原理同上,但必须在申请的内存前面多申请一个页面保存申请的页面数;


注意:

只能在C++中使用,windows/mac下测试通过。


使用方法:

只要include这个头文件即可,且内存必须是new出来的,而非malloc的。


参考:

1,http://www.wangchao.net.cn/bbsdetail_65784.html

2,http://blog.csdn.net/cjfeii/article/details/9122279

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值