C++ 技术中心

   :: 首页 :: 联系 ::  :: 管理
  160 Posts :: 0 Stories :: 87 Comments :: 0 Trackbacks

公告

郑重声明:本BLOG所发表的原创文章,作者保留一切权利。必须经过作者本人同意后方可转载,并注名作者(天空)和出处(CppBlog.com)。作者Email:coder@luckcoder.com

留言簿(27)

搜索

  •  

最新随笔

最新评论

评论排行榜

#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>
/*
*        ooooooooooooo      |  *******
(*)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>
/*
* ********* |ooooooooooooooooooooo    |  ***********
* 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

posted on 2014-08-22 16:53 C++技术中心 阅读(1472) 评论(0)  编辑 收藏 引用 所属分类: C++ STL

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理