一种检查内存访问越界的方法, 权当抛砖引玉

一种检查内存访问越界的方法, 权当抛砖引玉

最近搞一个IP摄像机的Client程序, 被一个bug搞得晕头转向.

具体问题是: 无论是编译成debug还是release, 只要连接crt debug版, 一点问题没有. 连接crt release版,一放视频就崩溃. 也不弹出异常, 程序也不死, 就是进程直接消失. 单步也找不到真正导致问题的代码, 出错断点都是乱糟糟的.

跟人讨论了一下基本确定是内存访问越界(把某对象的vptr抹掉了也说不定), 但是肉眼看不出来哪出的问题. 于是想这么个办法:

#ifndef __mem_bound_check_H__
#define  __mem_bound_check_H__

#define  MEM_PAGE_SIZE 4096

#include 
< Windows.h >

void   * operator   new (size_t size)
{
    
if(0 == size)
    
{
        size 
= 1;
    }

    
    
int page_num = (int)(size / MEM_PAGE_SIZE + (size % MEM_PAGE_SIZE ? 1 : 0));
    size_t aligned_size 
= page_num * MEM_PAGE_SIZE + 1;  //with a extra mem page for debug.
    size_t offset = page_num * MEM_PAGE_SIZE - size;
    
    
void *= ::VirtualAlloc(NULL, aligned_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    
if(NULL == p)
    
{
        
return NULL;
    }

    
    
void *pchecked = (char *)p + page_num * MEM_PAGE_SIZE;
    
    unsigned 
long old_protect;
    ::VirtualProtect(pchecked, MEM_PAGE_SIZE, PAGE_NOACCESS, 
&old_protect);
    
    
return (char *)p + offset;
}


void   operator  delete( void   * p)
{    
    p 
= (char *)p + (size_t)(p) % MEM_PAGE_SIZE;  //find real header addr of the mem block.

    
if(NULL == p)
    
{
        
return;
    }

    
    ::VirtualFree(p, 
0, MEM_RELEASE);
}


void   * operator   new [](size_t size)
{
    
if(0 == size)
    
{
        size 
= 1;
    }

    
    
int page_num = (int)(size / MEM_PAGE_SIZE + (size % MEM_PAGE_SIZE ? 1 : 0));
    size_t aligned_size 
= page_num * MEM_PAGE_SIZE + 1;  //with a extra mem page for debug.
    size_t offset = page_num * MEM_PAGE_SIZE - size;
    
    
void *= ::VirtualAlloc(NULL, aligned_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    
if(NULL == p)
    
{
        
return NULL;
    }

    
    
void *pchecked = (char *)p + page_num * MEM_PAGE_SIZE;
    
    unsigned 
long old_protect;
    ::VirtualProtect(pchecked, MEM_PAGE_SIZE, PAGE_NOACCESS, 
&old_protect);
    
    
return (char *)p + offset;    
}



void   operator  delete[]( void   * p)
{    
    p 
= (char *)p + (size_t)(p) % MEM_PAGE_SIZE;  //find real header addr of the mem block.

    
if(NULL == p)
    
{
        
return;
    }

    
    ::VirtualFree(p, 
0, MEM_RELEASE);
}


#endif   //  __mem_bound_check_H__


简单地说就是重载了new和new[], 分配内存的时候在后面附加上一页不能访问的内存. 这在越界时就会有异常了.
不知道还有没有什么更简单的方法?

==========================

更新: 我用这个方法检查出来的错误竟然在同事那里cp来的一段base64编码代码里. faint.

你可能感兴趣的:(一种检查内存访问越界的方法, 权当抛砖引玉)