⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mem.c

📁 C语言库函数的源代码,是C语言学习参考的好文档。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* +++Date last modified: 05-Jul-1997 */

/*
**  This is a copyrighted work which is functionally identical to work
**  originally published in Micro Cornucopia magazine (issue #52, March-April,
**  1990) and is freely licensed by the author, Walter Bright, for any use.
*/

/*_ mem.c   Fri Jan 26 1990   Modified by: Walter Bright */
/* $Header: /proj/products/merlin/port/RCS/mem.c,v 1.19 89/10/20 14:36:02 bright Exp Locker: bright $ */
/* Memory management package                    */

#if defined(VAX11C)
#define  __FILE__  "mem.c"
#endif

#include    <stdio.h>
#include    <stdlib.h>
#include    <io.h>

#ifndef MEM_H
#include    "mem.h"
#endif

#ifndef assert
#include    <assert.h>
#endif

#if defined(_MSC_VER)
#include    <dos.h>
#endif

#if !defined(VAX11C)
#ifdef BSDUNIX
#include <strings.h>
#else
#include <string.h>
#endif
#else
extern char *strcpy(),*memcpy();
extern int strlen();
#endif  /* VAX11C */

int mem_inited = 0;           /* != 0 if initialized              */

static int mem_behavior = MEM_ABORTMSG;
static int (*fp)() = (int (*)())NULL;    /* out-of-memory handler      */
static int mem_count;         /* # of allocs that haven't been free'd   */
static int mem_scount;        /* # of sallocs that haven't been free'd */
static int near mem_exception(); /* called when out of memory */

/* Determine where to send error messages */
#if defined(MSDOS) || defined(__MSDOS__)
#define ferr      stdout      /* stderr can't be redirected with MS-DOS */
#else
#define ferr      stderr
#endif

/*******************************/

void mem_setexception(flag,handler_fp)
#if defined(__cplusplus) && __cplusplus
enum MEM_E flag;
#else
int flag;
#endif
int (*handler_fp)();
{
    mem_behavior = flag;
    fp = (mem_behavior == MEM_CALLFP) ? handler_fp : 0;
#if defined(MEM_DEBUG) && MEM_DEBUG
    assert(0 <= flag && flag <= MEM_RETRY);
#endif
}

/*************************
 * This is called when we're out of memory.
 * Returns:
 *    1:    try again to allocate the memory
 *    0:    give up and return NULL
 */

static int near mem_exception()
{   int behavior;

    behavior = mem_behavior;
    while (1)
    {
      switch (behavior)
      {
          case MEM_ABORTMSG:
#if defined(MSDOS) || defined(__MSDOS__) || defined(__OS2__)
            /* Avoid linking in buffered I/O */
          { static char msg[] = "Fatal error: out of memory\r\n";

            write(1,msg,sizeof(msg) - 1);
          }
#else
            fputs("Fatal error: out of memory\n",ferr);
#endif
            /* FALL-THROUGH */
          case MEM_ABORT:
            exit(EXIT_FAILURE);
            /* NOTREACHED */
          case MEM_CALLFP:
            assert(fp);
            behavior = (*fp)();
            break;
          case MEM_RETNULL:
            return 0;
          case MEM_RETRY:
            return 1;
          default:
            assert(0);
      }
    }
}

/****************************/

#if defined(MEM_DEBUG) && MEM_DEBUG

#undef mem_strdup

char *mem_strdup(s)
const char *s;
{
      return mem_strdup_debug(s,__FILE__,__LINE__);
}

char *mem_strdup_debug(s,file,line)
char *file;
const char *s;
int line;
{
      char *p;

      p = s
          ? (char *) mem_malloc_debug((unsigned) strlen(s) + 1,file,line)
          : NULL;
      return p ? strcpy(p,s) : p;
}
#else
char *mem_strdup(s)
const char *s;
{
      char *p;

      p = s ? (char *) mem_malloc((unsigned) strlen(s) + 1) : NULL;
      return p ? strcpy(p,s) : p;
}

#endif /* MEM_DEBUG */

#ifdef MEM_DEBUG

static long mem_maxalloc;     /* max # of bytes allocated         */
static long mem_numalloc;     /* current # of bytes allocated           */

#define BEFOREVAL 0x12345678  /* value to detect underrun   */
#define AFTERVAL  0x87654321  /* value to detect overrun    */

#if SUN || SUN386
static long afterval = AFTERVAL;    /* so we can do &afterval     */
#endif

/* The following should be selected to give maximum probability that    */
/* pointers loaded with these values will cause an obvious crash. On    */
/* Unix machines, a large value will cause a segment fault.       */
/* MALLOCVAL is the value to set malloc'd data to.                */

#if MSDOS || __MSDOS__ || __OS2__
#define BADVAL          0xFF
#define MALLOCVAL 0xEE
#else
#define BADVAL          0x7A
#define MALLOCVAL 0xEE
#endif

/* Disable mapping macros     */
#undef      mem_malloc
#undef      mem_calloc
#undef      mem_realloc
#undef      mem_free

/* Create a list of all alloc'ed pointers, retaining info about where   */
/* each alloc came from. This is a real memory and speed hog, but who   */
/* cares when you've got obscure pointer bugs.                    */

static struct mem_debug
{     struct mh
      { struct mem_debug *Mnext;    /* next in list               */
        struct mem_debug *Mprev;    /* previous value in list     */
        char *Mfile;          /* filename of where allocated            */
        int Mline;            /* line number of where allocated   */
        unsigned Mnbytes;     /* size of the allocation           */
        long Mbeforeval;      /* detect underrun of data          */
      } m;
      char data[1];           /* the data actually allocated            */
} mem_alloclist =
{
   {  (struct mem_debug *) NULL,
      (struct mem_debug *) NULL,
      "noname",
      11111,
      0,
      BEFOREVAL
   },
   AFTERVAL
};

/* Convert from a void *to a mem_debug struct.  */
#define mem_ptrtodl(p)  ((struct mem_debug *) ((char *)p - sizeof(struct mh)))

/* Convert from a mem_debug struct to a mem_ptr.      */
#define mem_dltoptr(dl) ((void *) &((dl)->data[0]))

#define next            m.Mnext
#define prev            m.Mprev
#define file            m.Mfile
#define line            m.Mline
#define nbytes          m.Mnbytes
#define beforeval m.Mbeforeval

/*****************************
 * Set new value of file,line
 */

void mem_setnewfileline(ptr,fil,lin)
void *ptr;
char *fil;
int lin;
{
    struct mem_debug *dl;

    dl = mem_ptrtodl(ptr);
    dl->file = fil;
    dl->line = lin;
}

/****************************
 * Print out struct mem_debug.
 */

static void near mem_printdl(dl)
struct mem_debug *dl;
{
#if LPTR
      fprintf(ferr,"alloc'd from file '%s' line %d nbytes %d ptr x%lx\n",
            dl->file,dl->line,dl->nbytes,mem_dltoptr(dl));
#else
      fprintf(ferr,"alloc'd from file '%s' line %d nbytes %d ptr x%x\n",
            dl->file,dl->line,dl->nbytes,mem_dltoptr(dl));
#endif
}

/****************************
 * Print out file and line number.
 */

static void near mem_fillin(fil,lin)
char *fil;
int lin;
{
      fprintf(ferr,"File '%s' line %d\n",fil,lin);
      fflush(ferr);
}

/****************************
 * If MEM_DEBUG is not on for some modules, these routines will get
 * called.
 */

void *mem_calloc(u)
unsigned u;
{
      return mem_calloc_debug(u,__FILE__,__LINE__);
}

void *mem_malloc(u)
unsigned u;
{
      return mem_malloc_debug(u,__FILE__,__LINE__);
}

void *mem_realloc(p,u)
void *p;
unsigned u;
{
      return mem_realloc_debug(p,u,__FILE__,__LINE__);
}

void mem_free(p)
void *p;
{
      mem_free_debug(p,__FILE__,__LINE__);
}    


/**************************/

void mem_freefp(p)
void *p;
{
      mem_free(p);
}

/***********************
 * Debug versions of mem_calloc(), mem_free() and mem_realloc().
 */

void *mem_malloc_debug(n,fil,lin)
unsigned n;
char *fil;
int lin;
{   void *p;

    p = mem_calloc_debug(n,fil,lin);
    if (p)
      memset(p,MALLOCVAL,n);
    return p;
}

void *mem_calloc_debug(n,fil,lin)
unsigned n;
char *fil;
int lin;
{
    struct mem_debug *dl;

    do
      dl = (struct mem_debug *)
          calloc(sizeof(*dl) + n + sizeof(AFTERVAL) - 1,1);
    while (dl == NULL && mem_exception());
    if (dl == NULL)
    {
#if 0
      printf("Insufficient memory for alloc of %d at ",n);
      mem_fillin(fil,lin);
      printf("Max allocated was: %ld\n",mem_maxalloc);
#endif
      return NULL;

⌨️ 快捷键说明

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