www.pudn.com > EZW_.rar > MEMCHK.C


/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/ 
/* Adapted/reformated to suit my own coding style. Some changes to the  
 * printing. Also the defintion that enable/disable the memory checker. 
 * Added a few functions and definitions. 
 * 
 * Mow-Song, Ng 2/9/2002 
 * msng@mmu.edu.my 
 * http://www.pesona.mmu.edu.my/~msng 
 * 
 * I do not claim copyright to the code, but if you use them or modify them, 
 * please drop me a mail. 
 * 
 */ 
/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/ 
 
/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/ 
/* Original code from LiftPack */ 
/* 
 *  -*- Mode: ANSI C -*- 
 *  $Id: memchk.c,v 1.7 1996/11/18 18:49:11 fernande Exp $ 
 *  $Header: /sgi.acct/sweldens/cvs/liftpack/Util/memchk.c,v 1.7  
 *           1996/11/18 18:49:11 fernande Exp $ 
 *  Author: M. A. Sridhar 
 *  Modified: Gabriel Fernandez 
 * 
 *  This file has a memory leak checker which keeps track of all the 
 *  allocations and deallocations in order to see if some previously 
 *  allocated memory is not freed at the end of the execution of the 
 *  code. 
 *  The functions included are malloc, calloc, realloc, and free. 
 * 
 *  NOTE: It is important tht this program is not combined with any 
 *        other memory handler, because a list of allocations and 
 *        deallocations is kept with every call to 'malloc', 'calloc', 
 *        'realloc', and 'free'. If 'free' is used to deallocate a 
 *        memory segment allocated with other function that the ones in 
 *        this file, the program will segment fault because is trying to 
 *        delete a list entry which does not exists. 
 */ 
/* do not edit anything above this line */ 
 
#include  
#include "memchk.h" 
 
#undef calloc 
#undef realloc 
#undef malloc 
#undef free 
 
#include  
#include  
 
typedef unsigned long uLong; 
typedef unsigned char uChar; 
 
uLong magic_cookie = 0xf9a42bb1; /* Used to indicate "allocated" state */ 
 
/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/ 
struct BlockHeader { 
    uLong marker; 
    long  time; 
    struct BlockHeader* prev; 
    struct BlockHeader* next; 
    char*  file; 
    long  lineNo; 
    long  size; 
#ifdef DOUBLE 
    uChar dummy[4];   /* pad structure to a power of two */ 
#endif 
}; 
 
 
/* --------------------- Static variables --------------------------------- */ 
 
static struct BlockHeader* _AllocListHead = 0; /* Head of list of */ 
                                               /* allocated blocks */ 
static struct BlockHeader* _AllocListTail = 0; /* Tail of list of */ 
                                               /* allocated blocks */ 
static short        _LeakCheckerActive = 0; 
static long         _Time = 0;          /* Clock: ticks on every new and */ 
                                        /* delete */ 
 
static long         _MaxMem = 0;        /* Max memory used so far */ 
static long         _CurrentAlloc = 0;  /* Amount of memory currently */ 
                                        /* allocated */ 
static long         _BeginTime = 0;     /* Time at which leack checker was */ 
                                        /* instantiated */ 
/*------------------------------------------------------------------------- */ 
 
/* code */ 
 
/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/ 
/* 
 * Calloc function: same as Malloc, but initializes the content with 
 *                  zeros. 
 */ 
void *Calloc ( size_t n, size_t s, int line_no, char *file_name ) 
{ 
    size_t size = n*s; 
    uChar *buffer = (uChar *)Malloc ( size, line_no, file_name ); 
    int i; 
 
    for ( i=0 ; i<(int)size ; i++ ) 
        buffer[i] = 0; 
 
    return buffer; 
} 
 
 
/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/ 
/* 
 * Realloc function: reallocates a contiguous segment of memory using 
 *                   the same pointer variable. 
 */ 
void *Realloc ( void *p, size_t s, int line_no, char *file_name ) 
{ 
    uChar *newp; 
    struct BlockHeader* q; 
     
    /* Check for integrity of memory in p */ 
    q = (struct BlockHeader*) 
        ( (uChar*) p - sizeof (struct BlockHeader)); 
    if (q->marker != magic_cookie && _LeakCheckerActive) 
        fprintf (stderr, "Realloc(%8lx): memory corrupted", (long)p); 
 
    /* Allocate new segment and copy p into it */ 
    newp = (uChar *)Malloc ( s, line_no, file_name ); 
    newp = (uChar *)memcpy (newp, p, (size_t)q->size); 
 
    /* Free p and return new segment */ 
    Free (p); 
    return (void *)newp; 
} 
 
 
/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/ 
/* 
 * Malloc function: uses a linked list to keep track of all the memory 
 *                  segments that have been allocated so far. It 
 *                  includes information about the size of the segment, 
 *                  the file where the allocation was done, the line 
 *                  where the function was called, and the order in 
 *                  which the call was executed. 
 */ 
void* Malloc (size_t n, int line_no, char* file_name) 
{ 
    struct BlockHeader* q; 
    long size; 
    uChar* p; 
 
    if (n == 0) 
        return NULL; 
	 
    size = (long)n; 
    /* Allocate  extra bytes */ 
    p = (uChar*) malloc (n + sizeof (struct BlockHeader)); 
    if (!p) { 
        fprintf (stderr, "Malloc(): allocating %u bytes: no memory!", n); 
        exit (1); 
    } 
     
    _CurrentAlloc += (long)n; 
    if (_CurrentAlloc > _MaxMem) 
        _MaxMem = _CurrentAlloc; 
    q = (struct BlockHeader*) p; 
    /* Put a magic marker */ 
    q->marker = magic_cookie; 
    q->time   = _Time++; 
    q->size   = size; 
    q->file   = file_name; 
    q->lineNo = (long)line_no; 
    memset (p + sizeof(struct BlockHeader),  '\02', (unsigned int) size); 
    /* Uninitialized allocated memory has 02 in it */ 
     
	 /* Insert at tail of allocated list */ 
    if (_AllocListTail) { 
        _AllocListTail->next = q; 
        q->prev = _AllocListTail; 
        q->next = 0; 
        _AllocListTail = q; 
    } 
    else { 
        _AllocListHead = _AllocListTail = q; 
        q->prev = q->next = 0; 
    } 
    return p + sizeof(struct BlockHeader); 
} 
 
/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/ 
/* 
 * Free function: frees previously allocated memory and puts 03 in 
 *                it to verify later on. The entry in the linked list 
 *                is removed and all the other entries are reorganized. 
 */ 
void Free (void* p) 
{ 
    struct BlockHeader* q; 
     
    if ( p == NULL ) 
        fprintf (stderr, "Free(%8lx): empty memory\n", (long)p); 
    q = (struct BlockHeader*) 
        ( (uChar*) p - sizeof (struct BlockHeader)); 
    if (q->marker != magic_cookie && _LeakCheckerActive) 
        fprintf (stderr, "Free(%8lx): memory corrupted\n", (long)p); 
 
    _CurrentAlloc -= q->size; 
    if (_AllocListHead) { 
        if (q->prev) 
            q->prev->next = q->next; 
        if (q->next) 
            q->next->prev = q->prev; 
        if (q == _AllocListHead) 
            _AllocListHead = q->next; 
        if (q == _AllocListTail) 
            _AllocListTail = q->prev; 
        memset (q,  '\03', (unsigned int) (sizeof(struct BlockHeader) + 
                                           (unsigned int)q->size)); 
            /* Freed  memory has 03 in it */ 
    } 
    free (q); 
    _Time++; 
} 
 
 
/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/ 
/* 
 * PrintLeaks function: this routine prints the content of the linked 
 *                      list with all the information about memory 
 *                      allocated so far. If everything that was 
 *                      allocated was freed, then the list should be 
 *                      empty and nothing should be printed. 
*/ 
int PrintLeaks () 
{ 
 
#ifdef __MEMCHK_ENABLE_ 
 
	struct BlockHeader* q = _AllocListHead; 
	long count = 0; 
	 
	fprintf (stderr, "\nMemory status:\n" 
			"--------------\n"); 
	fprintf(stderr, "Max:%d  Current:%d\n", MaxMemory(), CurrentMemoryAllocated());	 
	while (q) { 
		if (q->time >= _BeginTime) 
			count++; 
		q = q->next; 
	} 
	if (count) { 
		q = _AllocListHead; 
		while (q) { 
			if (q->time >= _BeginTime) { 
				/* Only output if the allocation occurred after the leak */ 
				/* checker was created */ 
				fprintf (stderr, 
					"Time: %ld Address: %08x Size: %ld line %d file '%s'\n", 
					q->time, (unsigned long)q, q->size, 
					(int)q->lineNo, q->file); 
			} 
			q = q->next; 
		} 
		return 1; 
	} 
	else{ 
		fprintf(stderr, "No allocated memory.\n"); 
		return 0; 
	} 
 
#else 
 
	return 0; 
 
#endif 
 
} 
 
 
/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/ 
/* 
 * FreeLeaks functions: frees intermediate allocated memory that cannot 
 *                      be free'd by any other mean since an unexpected 
 *                      error has occurred. 
*/ 
void FreeLeaks () 
{ 
 
#ifdef __MEMCHK_ENABLE_ 
	struct BlockHeader* q   = _AllocListHead; 
	struct BlockHeader* tmp; 
	long count = 0; 
	while (q) { 
		if (q->time >= _BeginTime) 
			count++; 
		q = q->next; 
	} 
	if (count) { 
		q = _AllocListHead; 
		while (q) { 
			tmp = q->next; 
			if (q->time >= _BeginTime) { 
				/* Only free if the allocation occurred after the leak */ 
				/* checker was created */ 
				free (q); 
			} 
			q = tmp; 
		} 
	} 
	_AllocListHead = _AllocListTail = 0; 
	_CurrentAlloc = 0; 
#endif 
 
} 
 
 
/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/ 
/* 
 * MaxMemory functions: returns the maximum memory used so far.  
 * 
 */ 
long MaxMemory() 
{ 
#ifdef __MEMCHK_ENABLE_ 
	return _MaxMem; 
#else 
	return 0; 
#endif 
} 
 
/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/ 
/* 
 * MaxMemory functions: returns the maximum memory used so far.  
 * 
 */ 
long CurrentMemoryAllocated() 
{ 
#ifdef __MEMCHK_ENABLE_ 
	return _CurrentAlloc; 
#else 
	return 0; 
#endif 
} 
/*----------------------------------------------------------------------------*/ 
/*----------------------------------------------------------------------------*/