jmalloc.c

来自「国外网站上的一些精典的C程序」· C语言 代码 · 共 662 行 · 第 1/2 页

C
662
字号
/*--------------------------------------------------------------*//* Debugging extension by Jeff Dunlop                           *//* Copyright 1992-1993, DB/Soft Publishing Co.                  *//* License is hereby granted for use of JMalloc as a debugging  *//* aid in any program.  JMalloc may not be sold or distributed  *//* as or part of any for-profit debugging program or library    *//* nor may it be included in any for-profit library that offers *//* debugging features.  Any redistribution of JMalloc source    *//* must include this copyright notice.                          *//*--------------------------------------------------------------*//*-------------------------[ jmalloc.c ]------------------------*//*                 drop-in for malloc with diags                *//*--------------------------------------------------------------*//*--------------------------------------------------------------*//*---------------------------[ notes ]--------------------------*//*--------------------------------------------------------------*//*The J... macros are intended for use on JMalloc'd memory blocks.  TheA... macros are intended for use on auto array blocks and will onlywork if the base of the array is passed.  They will not work if theaddress of an array element is passed.  All functions are designed tobe nearly drop-in replacements for standard library functions.  The onecase where debugging libraries traditionally fall short is when a blockoperation occurs on an automatic array in a position other than at thehead.  This library could conceivably be extended to include a class offunctions that allow you to pass both a block and an offset into thatblock so that the block and its size can be checked.  My style ofprogramming eschews this practice so I haven't had any motivation to soextend this library.  Note that such an extension would depart slightlyfrom the standard syntax of the runtime library because of theadditional passed parameter.JMemcheck(0) may be called at any time for an overwrite check of allallocated blocks.  JMemcheck(1) additionally checks for orphaned blocksand should be called just before program shutdown.All functions are designed to log any detectable errors when the errorsoccur, and to report either the line number of the overwrite, or theline number that the block was allocated on, depending on which is moreuseful.  Any blocks that are damaged by non-JMalloc functions will notbe noticed until they are JFree'd and will be tougher to debug.Regardless of the damage that a function call produces, JMalloc neverdeparts from the runtime library's behavior.  Its job is to report,nothing more.  All allocated blocks (except for JCalloc calls) aredirtied and all blocks are dirtied before they are freed.  If you arereferencing freed memory or not initializing a new block, it will bevery obvious.  All blocks have an extra check byte that is checked whenthe block is freed or during JMemcheck.  This doesn't catch randommemory writes, but it does catch overruns.*//*--------------------------------------------------------------*//*-----------------------[ header files ]-----------------------*//*--------------------------------------------------------------*/#define DBUG#if defined __TURBOC__ #include <alloc.h> #include <mem.h>#else #if defined(__ZTC__)  #include <dos.h> #else  #include <malloc.h> #endif#endif#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "jmalloc.h"/*--------------------------------------------------------------*//*--------------------[ local prototypes ]----------------------*//*--------------------------------------------------------------*/static MLINK *JMemOwner(char *Addr);/*--------------------------------------------------------------*//*---------------------[ global variables ]---------------------*//*--------------------------------------------------------------*/MLINK *MalTop;                        /* top of allocation chain */void db_prn(char *fmt, ...){    va_list p;    va_start(p, fmt);    vprintf(fmt, p);    putchar('\n');    va_end(p);}void *j_deref(void *a, char *file, int line){    if ( a == NULL )    {        DBUG_PRINT("alloc", ("Dereferenced NULL pointer - %s: line %d",            file, line));    }    return a;}/*-------------------------[ j_malloc ]-------------------------*//*            Memory allocator with diagnostics                 *//*--------------------------------------------------------------*//* input:                                                       *//*      Size = number of bytes to allocate                      *//* local:                                                       *//*      CurMal = pointer current mem struct                     *//*      PrevMal = pointer to previous mem struct                *//*      AllocAddr = pointer to allocated ram                    *//* return:                                                      *//*      address of allocated ram, or NULL on error              *//* note:                                                        *//*       use the JMalloc macro                                  *//*--------------------------------------------------------------*/static int memc;void *j_malloc(unsigned Size, char *file, int line){    /* 1. Allocate the memory */    /* 2. Add to allocation chain */    /* 3. Fill with non-null */    MLINK *CurMal = MalTop,          *PrevMal;    void *AllocAddr;    /* Allocate the memory + 1 (for check byte) */    if ( (AllocAddr = malloc(Size + 1)) == NULL )    {        DBUG_PRINT("alloc", ("Allocation failed: %s Line %d", file, line));        return((void*)0);    }    /* Add to the allocation chain */    PrevMal = CurMal;    while ( CurMal != NULL )    {        PrevMal = CurMal;        CurMal = CurMal->NextLink;    }    if ( (CurMal = malloc(sizeof *CurMal)) == NULL )    {        DBUG_PRINT("alloc", ("Control allocation failed: %s Line %d", file,            line));        return(AllocAddr);    }    /* Deal with bootstrap */    if ( PrevMal == NULL )        MalTop = CurMal;    else        PrevMal->NextLink = CurMal;    CurMal->NextLink = NULL;    CurMal->MAddr = AllocAddr;    CurMal->MSize = Size;    CurMal->MLine = line;    AStrCpy(CurMal->MFile, file);    memset(AllocAddr, CKBYT, Size + 1);    memc++;    return(AllocAddr);}/*-------------------------[ j_calloc ]-------------------------*//*            Memory allocator with diagnostics                 *//*--------------------------------------------------------------*//* method:                                                      *//*      - Allocate the memory via JMalloc                       *//*      - Fill with null                                        *//*      - Set check-byte                                        *//* input:                                                       *//*      Size = number of bytes to allocate                      *//* local:                                                       *//*      CurCal = pointer current mem struct                     *//*      PrevCal = pointer to previous mem struct                *//*      AllocAddr = pointer to allocated ram                    *//* return:                                                      *//*      address of allocated ram, or NULL on error              *//*  note:                                                       *//*      Use the JCalloc macro                                   *//*--------------------------------------------------------------*/void *j_calloc(unsigned Size, unsigned SizEach, char *file, int line){    char *AllocAddr;    /* Allocate the memory + 1 (for check byte) */    /* Do not piss over NULL return - JMalloc handled that */    if ( (AllocAddr = j_malloc(Size * SizEach, file, line)) != NULL )    {        /* Prep allocated ram */        memset(AllocAddr, 0, Size * SizEach);        AllocAddr[Size * SizEach] = CKBYT;    }    return(AllocAddr);}/*-------------------------[ j_realloc ]------------------------*//*                     Reallocate memory                        *//*--------------------------------------------------------------*//* input:                                                       *//*  Addr = block's current address                              *//*  Size = block's new size                                     *//* return:                                                      *//*  Block's new address, or NULL if memory not available.       *//* note:                                                        *//*  Use the JRealloc macro.                                     *//*  If NULL is returned, Addr was also freed                    *//*--------------------------------------------------------------*/void *j_realloc(void *Addr, unsigned Size, char *file, int line){    MLINK *CurMal = MalTop;    void *tmp;    if ( Addr == NULL )        return(j_malloc(Size, file, line));    /* Find the old block in the alloc list */    while ( CurMal->MAddr != Addr && CurMal != NULL )        CurMal = CurMal->NextLink;    if ( CurMal == NULL )    {        /* Just call the standard realloc since we don't know anything         * about this block         */        DBUG_PRINT("alloc", ("Realloc attempted on unrecorded block: %s "            "Line %d", file, line));        return(realloc(Addr, Size));    }    else    {        tmp = j_malloc(Size, file, line);        if ( tmp != NULL )        {            memcpy(tmp, Addr, min(CurMal->MSize, Size));            j_free(Addr, file, line);        }        else        {            j_free(Addr, file, line);            return NULL;        }    }    return(tmp);}/*-------------------------[ j_free ]---------------------------*//*           Memory deallocator with diagnostics                *//*--------------------------------------------------------------*//* input:                                                       *//*      AllocAddr = pointer to ram to deallocate                *//* local:                                                       *//*      CurMal = pointer to current mem struct                  *//*      PrevMal = pointer to prev mem struct                    *//* note:                                                        *//*      This function is designed to be implemented with the    *//*      macro JFree                                             *//*--------------------------------------------------------------*/void j_free(void *AllocAddr, char *file, int line){    /* 1. Find the block in the alloc list */    /* 2. Check for check-byte overwrite   */    /* 3. Remove allocation record         */    /* 3. Free the ram                     */    MLINK *CurMal = MalTop,          *PrevMal = MalTop;    /* Find the block in the alloc list */    while ( CurMal != NULL && CurMal->MAddr != AllocAddr )    {        PrevMal = CurMal;        CurMal = CurMal->NextLink;    }    if ( CurMal == NULL )    {        DBUG_PRINT("alloc", ("Freeing an unrecorded block: %s %d", file,            line));    }    else    {        /* Check for check-byte overwrite */        if ( CurMal->MAddr[CurMal->MSize] != CKBYT )            DBUG_PRINT("alloc", ("Memory overrun detected on block allocated"            " at %s Line %d", CurMal->MFile, CurMal->MLine));        memset(AllocAddr, DIRTY, CurMal->MSize + 1);        if ( CurMal == MalTop )            MalTop = CurMal->NextLink;        else            PrevMal->NextLink = CurMal->NextLink;        free(CurMal);    }    /* Free the ram regardless of validity */    free(AllocAddr);    memc--;    return;}/*-------------------------[ JMemcheck ]------------------------*//*                Verify memory chain integrity                 *//*--------------------------------------------------------------*//* input:                                                       *//*  CheckFree != if currently allocated blocks are to be        *//*  reported                                                    *//* local:                                                       *//*      i = link number                                         *//*      CurMal = link pointer                                   *//*      status = current error condition                        *//* return:                                                      *//*      -1 = error,                                             */

⌨️ 快捷键说明

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