Borland Online And The Cobb Group Present:


September, 1995 - Vol. 2 No. 9


Listing D: DMALLOC.C


//*************************************************
// DMALLOC.C - Contains "thunk" functions for
//     trapping calls to malloc and free. Also,
//     contains dreport(), which writes a memory
//     status report to the file DREPORT.LST.
//

#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <string.h>

#define GROWBY 100

//----Compile only if DEBUG is defined
#ifdef __DEBUG

//----Here's the structure we save for each
//    memory allocation
typedef struct _DLIST {
    void  *ptr;
    char  *file;
    int   line;        
} DLIST;

//----Global variables
DLIST **dlist;
int dlist_cnt;
int dlist_size;

//*************************************************
// dmalloc - This is our thunk for malloc
//
void *dmalloc( char *file, int line, size_t size )
{
    void   *ptr;
    DLIST **new_dlist;
    int     new_dlist_size;

    //----Create list the first time through
    if ( !dlist )
    {
        dlist = (DLIST **)
            malloc( sizeof(DLIST *) * GROWBY );
        if ( !dlist )
            return NULL;
        dlist_cnt = 0;
        dlist_size = GROWBY;
    }

    //----Enlarge list when necessary
     if ( dlist_cnt+1 > dlist_size )
    {
        new_dlist_size = 
            min( dlist_size+GROWBY, 16380 );
        new_dlist = (DLIST **)
            realloc( dlist, 
                sizeof(DLIST *) * new_dlist_size );
        if ( !new_dlist )
            return NULL;    // Not enough memory
        dlist = new_dlist;
        dlist_size = new_dlist_size;
    }

    //----Allocate memory for new DLIST object
    dlist[dlist_cnt] = 
        (DLIST *)malloc( sizeof(DLIST) );
    if ( !dlist[dlist_cnt] )
        return NULL;        // Not enough memory
    dlist[dlist_cnt]->file =
        malloc( strlen(file)+1 );
    if ( !dlist[dlist_cnt]->file )
    {
        free ( dlist[dlist_cnt] );
        return NULL;        // Not enough memory
    }

    //----Allocate the requested memory
    ptr = malloc( size );
    if ( !ptr )
        return NULL;        // Not enough memory
    
    //----Update dlist with pointer information
    dlist[dlist_cnt]->ptr = ptr;
    dlist[dlist_cnt]->line = line;
    strcpy( dlist[dlist_cnt]->file, file );
    ++dlist_cnt;

    //----Return pointer to caller
    return ptr;
}

//*************************************************
// dfree - This is our thunk for free
//
void dfree( void *ptr )
{
    int i = 0;

    //----Free the memory as requested
    free( ptr );

    //----Search for pointer in dlist
    while( i < dlist_cnt && ptr != dlist[i]->ptr )
        ++i;
    
    if ( i == dlist_cnt )     // Not in dlist
        return;

    //----Free associated dlist entry
    free( dlist[i]->file );
    free( dlist[i] );
    --dlist_cnt;

    //----Move last entry to fill the hole in dlist
    if ( dlist_cnt > 0 && dlist_cnt != i )
        dlist[i] = dlist[dlist_cnt];
}

//*************************************************
// dreport - Writes the current dlist to a file

int dreport( void )
{
    int   i;
    FILE *fp;
    char  workstr[80];

    fp = fopen( "DREPORT.LST", "w" );
    if ( !fp )
        return 0;

    sprintf( workstr, "\n%d entries in dlist\n\n",
        dlist_cnt );
    fputs( workstr, fp );

    for ( i=0; i<dlist_cnt; i++ )
    {
        sprintf( workstr, "Line: %5.5d File: %s\n",
            dlist[i]->line, dlist[i]->file );
        fputs( workstr, fp );
    }

    fclose( fp );
    return 1;
}
#endif


Return to "Debugging Tip - Using thunk functions to track down memory leaks"


Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.