memtrack.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 572 行 · 第 1/2 页

C
572
字号
    char        *p1;

    p1 = name;
    while( *p1 ) {
        ++p1;
    }
    trk = alloc( sizeof( tracker ) + ( p1 - name ) );
#ifdef _EXTRA_MEM
    if( ExtMem == 0 ) {
        ExtMem = ExtMemAlloc( TRACK_SIZE );
        if( ExtMem == (void FAR *)0 ) {
            ExtMem = ExtMemAlloc( ExtMemAvail() );
        }
        TrkFrl = 0;
        TrkBeg = ExtMem;
    }
#endif
    if( trk == 0 ) return( 0 );
    trk->mem_a_list = 0;
    trk->mem_used   = 0;
    trk->max_mem    = 0;
    trk->alloc      = alloc;
    trk->realloc    = realloc;
    trk->free       = free;
    trk->prt_line   = prt_line;
    CopyStr( name, trk->name );
    return( trk );
}

extern  void    TrCheck( tracker *trk ) {
/***************************************/

    TRPTR       alloc;

    alloc = trk->mem_a_list;
    while( alloc != 0 ) {
        TrValidate( Mem( alloc ), TR_NO_ROUTINE, trk );
        alloc = Next( alloc );
    }
}

extern  void    TrMemFini( tracker *trk ) {
/*****************************************/

    unsigned    chunks;
    TRPTR       alloc;

    chunks = 0;
    alloc = trk->mem_a_list;
    while( alloc != 0 ) {
        ++chunks;
        alloc = Next( alloc );
    }
    if( chunks != 0 ) {
        TrPrt( trk, "%NMemFini: %U chunks (%L bytes) unfreed",
             chunks, trk->mem_used );
    }
    while( trk->mem_a_list != 0 ) {
        TrValidate( Mem( trk->mem_a_list ), TR_NO_ROUTINE, trk );
        TrFree( Mem( trk->mem_a_list ), trk );
    }
    _Free( trk );
#ifdef _EXTRA_MEM

    ExtMemFree( ExtMem );

#endif
}

extern  void    TrPrtUsage( tracker *trk ) {
/******************************************/

    TrPrt( trk, "%N Memory usage: %L bytes", trk->max_mem );
}

extern  void    TrPrtMemUse( tracker *trk ) {
/*******************************************/

    TRPTR       alloc;

    TrPrtUsage( trk );
    alloc = trk->mem_a_list;
    if( alloc == 0 ) return;
#if defined(__SMALL__) || defined(__MEDIUM__)
    TrPrt( trk, " Who  Addr Size" );
    TrPrt( trk, " ==== ==== ====" );
#else
    TrPrt( trk, " Who      Addr     Size" );
    TrPrt( trk, " ======== ======== ====" );
#endif
    do {
        TrPrt( trk, "&%C %D %U", Who( alloc ), Mem( alloc ), Size( alloc ) );
        alloc = Next( alloc );
    } while( alloc != 0 );
}

extern  void *TrAlloc( unsigned size, void (*ra)(), tracker *trk ) {
/******************************************************************/

    void        *chunk;
    TRPTR       trchunk;

    if( size == 0 ) {
        TrPrt( trk, "%W size zero allocation", "Alloc", ra );
        return( 0 );
    }
    chunk = _Alloc( size + 1 );
    if( chunk != 0 ) {
        trchunk = AllocTrk( trk );
        if( trchunk == 0 ) {
            _Free( chunk );
            return( 0 );
        }
        SetNext( trchunk, trk->mem_a_list );
        SetWho( trchunk, ra );
        SetSize( trchunk, size );
        SetMem( trchunk, chunk );
        trk->mem_a_list = trchunk;
        trk->mem_used += size;
        if( trk->mem_used > trk->max_mem ) {
            trk->max_mem = trk->mem_used;
        }
        Fill( chunk, size + 1, ALLOC_BYTE );
    }
    return( chunk );
}

static int ValidChunk( TRPTR entry, char *who, void (*ra)(), tracker *trk ) {
/****************************************************************************/

    void    *chunk;

    chunk = Mem( entry );
    if( *((char *)_PtrAdd( chunk, Size(entry) )) != ALLOC_BYTE ) {
        TrPrt( trk, "%W %D overrun allocation of %U bytes", who, ra,
             chunk, Size(entry) );
        return( FALSE );
#ifdef _SYS_CHKS
    } else if( !MemOk( chunk, Size( entry ) + 1 ) ) {
        TrPrt( trk, "%W boundry tag hammered %D", who, ra, chunk );
        return( FALSE );
    } else if( ( chunk = MemOtherOk() ) != 0 ) {
        TrPrt( trk, "%W bad free list entry at %D", who, ra, chunk );
        return( FALSE );
#endif
    }
    return( TRUE );
}

extern  int    TrValidate( void *chunk, void (*ra)(), tracker *trk ) {
/*************************************************************************/

    TRPTR       entry;

    entry = trk->mem_a_list;
    for(;;) {
        if( entry == 0 ) {
            TrPrt( trk, "%W unowned chunk %D", "Validate", ra, chunk );
            return( FALSE );
        }
        if( _PT( Mem( entry ) ) == _PT( chunk ) ) break;
        entry = Next( entry );
    }
    return( ValidChunk( entry, "Validate", ra, trk ) );
}


extern  int    TrChkRange( void *start, unsigned len,
                            void (*ra)(), tracker *trk ) {

    TRPTR       ptr;
    void        *end;
    void        *end_chunk;

    ptr = trk->mem_a_list;
    for(;;) {
        if( ptr == 0 ) {
            TrPrt( trk, "%W %D not in any allocation", "ChkRange", ra, start );
            return( FALSE );
        }
        end_chunk = _PtrAdd( Mem( ptr ), Size( ptr ) );
        if( _PT( start ) >= _PT( Mem( ptr ) )
            && _PT( start ) < _PT( end_chunk ) ) break;
        ptr = Next( ptr );
    }
    end = _PtrAdd( start, len );
    if( _PT( end ) > _PT( end_chunk ) ) {
        TrPrt( trk, "%W %D+%U overruns allocation %D+%U", "ChkRange", ra,
                start, len, Mem( ptr ), Size( ptr ) );
        return( FALSE );
    }
    return( ValidChunk( ptr, "ChkRange", ra, trk ) );
}

extern  int     TrFree( void *chunk, tracker *trk ) {
/*****************************************************/

    return( TrFreeSize( chunk, 0, trk ) );
}

extern  int     TrFreeSize( void *chunk, unsigned given_size, tracker *trk ) {
/**************************************************************************/

    unsigned    size;
    TRPTR       entry;
    TRPTR       prev;
    int         ret;

    if( chunk == 0 ) return( TRUE );
    prev = 0;
    entry = trk->mem_a_list;
    for(;;) {
        if( entry == 0 ) {
            TrPrt( trk, "%W unowned chunk %D", "Free", TR_NO_ROUTINE, chunk );
            return( FALSE );
        }
        if( _PT( chunk ) == _PT( Mem( entry ) ) ) break;
        prev = entry;
        entry = Next( entry );
    }
    ret = ValidChunk( entry, "Free", TR_NO_ROUTINE, trk );
    if( prev == 0 ) {
        trk->mem_a_list = Next( entry );
    } else {
        SetNext( prev, Next( entry ) );
    }
    size = Size( entry );
    trk->mem_used -= size;
    FreeTrk( entry, trk );
    Fill( chunk, size + 1, FREED_BYTE );
    _Free( chunk );
    if( given_size != 0 && given_size != size ) {
        TrPrt( trk, "%W %D allocated %U, freed %U", "FreeSize", TR_NO_ROUTINE,
            chunk, size, given_size );
        return( FALSE );
    }
    return( ret );
}

extern void * TrReAlloc( void *old, unsigned size, void (*ra)(), tracker *trk )
/*****************************************************************************/
// reallocate a block of memory
{
    unsigned    sizeold;
    TRPTR       entry;
    TRPTR       prev;
    void        *chunk;

    if( size == 0 ) {
        TrPrt( trk, "%W size zero reallocation", "ReAlloc", ra );
        return( 0 );
    }
    if( old == 0 ) {
        TrPrt( trk, "%W reallocation of a NULL pointer", "ReAlloc", ra );
        return( 0 );
    }
    prev = 0;
    entry = trk->mem_a_list;
    for(;;) {
        if( entry == 0 ) {
            TrPrt( trk, "%W unowned chunk %D", "ReAlloc", TR_NO_ROUTINE, old );
            return( 0 );
        }
        if( _PT( old ) == _PT( Mem( entry ) ) ) break;
        prev = entry;
        entry = Next( entry );
    }
    if( !ValidChunk( entry, "ReAlloc", TR_NO_ROUTINE, trk ) ) {
        return( 0 );
    }
    sizeold = Size( entry );
    chunk = _ReAlloc( old, size + 1 );
    if( chunk != 0 ) {
        SetWho( entry, ra );
        SetSize( entry, size );
        SetMem( entry, chunk );
        trk->mem_used -= sizeold;
        trk->mem_used += size;
        if( trk->mem_used > trk->max_mem ) {
            trk->max_mem = trk->mem_used;
        }
        *((char *)chunk + size) = ALLOC_BYTE;
    }
    return( chunk );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?