次奥,折腾几天,内存检测工具写出来了

   
#include <stdarg.h>   
   
#include "dbg.h"   
#undef new   
#undef delete   
   
#ifndef NDEBUG   
//输出调试信息   
void dbgout( const char* fmt, ... )   
{   
    char str[4096];   
    va_list v;   
    va_start( v, fmt );   
    vsprintf( str, fmt, v );   
    strcat( str, "\n" );   
#ifdef _UNIX   
    fputs( str, stderr );   
#endif   
#ifdef _WIN32   
    ::OutputDebugString( str );   
#endif   
}   
   
struct alloc_node   
{   
    alloc_node* lptr;   /*记录申请记录节点左子树*/   
    alloc_node* rptr;   /*记录申请记录节点右子树*/   
    size_t      len;        /*申请的长度(不包括前后的保护长度)*/   
    CPCHAR      file;   /*申请内存的代码所在文件*/   
    UINT        line;       /*申请内存代码所在的行*/   
};   
   
static alloc_node* g_heap = NULL;/*堆的申请记录树根节点*/   
static alloc_node* g_vector_heap = NULL;/*vector堆的申请记录树根节点*/   
   
// Our magic guard bytes申请内存前后加上的保护字节   
static BYTE g_guard[] =   
{   
    0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,   
    0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF   
};   
//在堆中申请一块内存(可以申请空内存n=0)   
void* operator new( size_t n, CPCHAR file, UINT line )   
{   
    BYTE* pmem = NULL;   
    if( !n ) n = 1;/**/   
    alloc_node* pnode = (alloc_node*)malloc( n + 2*sizeof(g_guard) + sizeof(alloc_node) );   
    if( pnode )   
    {   
        pmem = (BYTE*)pnode + sizeof(alloc_node) + sizeof(g_guard);   
        memcpy( pmem - sizeof(g_guard), g_guard, sizeof(g_guard) );   
        memset( pmem, time(NULL), n );/*申请的数据空间会暂时存放分配时间*/   
        memcpy( pmem + n, g_guard, sizeof(g_guard) );   
   
        pnode->lptr = pnode->rptr = NULL;   
        pnode->len = n;   
        pnode->file = file;   
        pnode->line = line;   
        alloc_node** ppuplink = &g_heap;   
        alloc_node* pcur = g_heap;   
     //按照内存分配的位置将分配记录组成二叉树,把新分配的记录放入二叉树的对应位置   
        while( pcur )   
        {   
            if( pnode == pcur )   
            {   
                dbgout( "*** FATAL: duplicate memory allocated ***" );/*重复分配内存出错*/   
                assert( false );   
                exit( -1 );   
            }   
            if( pnode < pcur )   
            {   
                ppuplink = &pcur->lptr;   
                pcur = pcur->lptr;   
            }   
            else   
            {   
                ppuplink = &pcur->rptr;   
                pcur = pcur->rptr;   
            }   
        }   
        *ppuplink = pnode;   
    }   
   
    return pmem;   
}   
//在vector请一块内存(可以申请空内存n=0)   
void* operator new[]( size_t n, CPCHAR file, UINT line )   
{   
    BYTE* pmem = NULL;   
    if( !n ) n = 1;   
    alloc_node* pnode = (alloc_node*)malloc( n + 2*sizeof(g_guard) + sizeof(alloc_node) );   
    if( pnode )   
    {   
        pmem = (BYTE*)pnode + sizeof(alloc_node) + sizeof(g_guard);   
        memcpy( pmem - sizeof(g_guard), g_guard, sizeof(g_guard) );   
        memset( pmem, time(NULL), n );   
        memcpy( pmem + n, g_guard, sizeof(g_guard) );   
   
        pnode->lptr = pnode->rptr = NULL;   
        pnode->len = n;   
        pnode->file = file;   
        pnode->line = line;   
        alloc_node** ppuplink = &g_vector_heap;   
        alloc_node* pcur = g_vector_heap;   
        while( pcur )   
        {   
            if( pnode == pcur )   
            {   
                dbgout( "*** FATAL: duplicate memory allocated ***" );   
                assert( false );   
                exit( -1 );   
            }   
            if( pnode < pcur )   
            {   
                ppuplink = &pcur->lptr;   
                pcur = pcur->lptr;   
            }   
            else   
            {   
                ppuplink = &pcur->rptr;   
                pcur = pcur->rptr;   
            }   
        }   
        *ppuplink = pnode;   
    }   
   
    return pmem;   
}   
   
void operator delete( void* p )   
{   
    if( !p ) return;   
    if( !g_heap )   
    {   
        dbgout( "*** FATAL: delete with empty heap ***" );   
        assert( false );   
        exit( -1 );   
    }   
   
    alloc_node* pcur = g_heap;   
    alloc_node** ppuplink = &g_heap;   
    while( pcur )   
    {   
        void* pcurblk = (char*)pcur + sizeof(alloc_node) + sizeof(g_guard);   
        if( p == pcurblk )   
        {   
            BYTE* pmem = (BYTE*)p;   
         //比较申请内存的前后保护字节段是否正确   
            if( memcmp( pmem - sizeof(g_guard), g_guard, sizeof(g_guard) ) != 0 ||   
                memcmp( pmem + pcur->len, g_guard, sizeof(g_guard) ) != 0 )   
            {   
                dbgout( "*** FATAL: corrupted memory at %08X", p );   
                assert( false );   
                exit( -1 );   
            }   
            memset( pmem, time(NULL), pcur->len );   
            if( pcur->lptr && pcur->rptr )   
            {   
                // node has both ptrs so replace it with left child and move   
                // right child to bottom right of left child's tree   
                alloc_node* pend = pcur->lptr;   
                while( pend->rptr ) pend = pend->rptr;   
                *ppuplink = pcur->lptr;   
                pend->rptr = pcur->rptr;   
            }   
            else   
            {   
                // move child up   
                *ppuplink = (pcur->lptr) ? pcur->lptr : pcur->rptr;   
            }   
            free( pcur );   
            return;   
        }   
        if( p < pcurblk )   
        {   
            ppuplink = &pcur->lptr;   
            pcur = pcur->lptr;   
        }   
        else   
        {   
            ppuplink = &pcur->rptr;   
            pcur = pcur->rptr;   
        }   
    }   
   
    dbgout( "*** FATAL: delete on unalloced memory ***" );   
    assert( false );   
    exit( -1 );   
}   
   
void operator delete[]( void* p )   
{   
    if( !p ) return;   
    if( !g_vector_heap )   
    {   
        dbgout( "*** FATAL: delete with empty heap ***" );   
        assert( false );   
        exit( -1 );   
    }   
   
    alloc_node* pcur = g_vector_heap;   
    alloc_node** ppuplink = &g_vector_heap;   
    while( pcur )   
    {   
        void* pcurblk = (char*)pcur + sizeof(alloc_node) + sizeof(g_guard);   
        if( p == pcurblk )   
        {   
            BYTE* pmem = (BYTE*)p;   
            if( memcmp( pmem - sizeof(g_guard), g_guard, sizeof(g_guard) ) != 0 ||   
                memcmp( pmem + pcur->len, g_guard, sizeof(g_guard) ) != 0 )   
            {   
                dbgout( "*** FATAL: corrupted memory at %08X", p );   
                assert( false );   
                exit( -1 );   
            }   
            memset( pmem, time(NULL), pcur->len );   
            if( pcur->lptr && pcur->rptr )   
            {   
                // node has both ptrs so replace it with left child and move   
                // right child to bottom right of left child's tree   
                alloc_node* pend = pcur->lptr;   
                while( pend->rptr ) pend = pend->rptr;   
                *ppuplink = pcur->lptr;   
                pend->rptr = pcur->rptr;   
            }   
            else   
            {   
                // move child up   
                *ppuplink = (pcur->lptr) ? pcur->lptr : pcur->rptr;   
            }   
            free( pcur );   
            return;   
        }   
        if( p < pcurblk )   
        {   
            ppuplink = &pcur->lptr;   
            pcur = pcur->lptr;   
        }   
        else   
        {   
            ppuplink = &pcur->rptr;   
            pcur = pcur->rptr;   
        }   
    }   
   
    dbgout( "*** FATAL: delete on unalloced memory ***" );   
    assert( false );   
    exit( -1 );   
}   
   
void* operator new( size_t n )   
{   
    return ::operator new( n, "(unknown)", 0 );   
}   
   
void* operator new[]( size_t n )   
{   
    return ::operator new[]( n, "(unknown)", 0 );   
}   
//在内存分配树中遍历,寻找总共分配的长度   
static void walk_alloc_tree( alloc_node* pcur, size_t* pttl )   
{   
    if( pcur )   
    {   
        walk_alloc_tree( pcur->lptr, pttl );   
        dbgout( "%s(%u): %u bytes at %08X", pcur->file, pcur->line,   
                pcur->len, (char*)pcur + sizeof(alloc_node) );   
        *pttl += pcur->len;   
        walk_alloc_tree( pcur->rptr, pttl );   
    }   
}   
//显示堆中分配的内存记录   
void dump_alloc_heaps( void )   
{   
    if( g_heap || g_vector_heap )   
    {   
        size_t ttl = 0;   
        dbgout( "Memory leaks detected" );   
        dbgout( "=====================" );   
        dbgout( "" );   
   
        if( g_heap )   
        {   
            dbgout( "Scalar objects" );   
            dbgout( "--------------" );   
            walk_alloc_tree( g_heap, &ttl );   
            dbgout( "" );   
        }   
        if( g_vector_heap )   
        {   
            dbgout( "Vector objects" );   
            dbgout( "--------------" );   
            walk_alloc_tree( g_vector_heap, &ttl );   
            dbgout( "" );   
        }   
   
        dbgout( "=====================" );   
        dbgout( "Total bytes: %u", ttl );   
        dbgout( "=====================" );   
    }   
}   
   
#endif   

 

posted @ 2013-06-28 14:33  方东信  阅读(461)  评论(0编辑  收藏  举报