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

📄 mpalloc.c

📁 debug source code under unix platform.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * mpatrol * A library for controlling and tracing dynamic memory allocations. * Copyright (C) 1997-2002 Graeme S. Roy <graeme.roy@analog.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307, USA. *//* * Release version of library interface.  This module defines the visible * interface for the mpatrol library in release mode.  These functions * should not normally be required if all of the source files that use * mpatrol.h were recompiled with NDEBUG, but they are defined here just * in case. */#include "inter.h"#include "mpalloc.h"#include "version.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#if TARGET == TARGET_UNIX#include <unistd.h>#if SYSTEM == SYSTEM_LINUX#include <malloc.h>#endif /* SYSTEM */#elif TARGET == TARGET_WINDOWS#include <windows.h>#include <winbase.h>#elif TARGET == TARGET_NETWARE#include <nwthread.h>#include <nks/memory.h>#endif /* TARGET */#if MP_IDENT_SUPPORT#ident "$Id: mpalloc.c,v 1.44 2002/01/08 20:13:59 graeme Exp $"#else /* MP_IDENT_SUPPORT */static MP_CONST MP_VOLATILE char *mpalloc_id = "$Id: mpalloc.c,v 1.44 2002/01/08 20:13:59 graeme Exp $";#endif /* MP_IDENT_SUPPORT *//* An allocaheader belongs to a stack of memory allocations that were made * by the alloca() and related functions.  Some memory allocations at the * top of the stack may be automatically freed when the next call to allocate * memory is made and the stack has been unwound. */typedef union allocaheader{#if MP_LONGLONG_SUPPORT  long long integer;            /* type with most restrictive alignment */#else /* MP_LONGLONG_SUPPORT */  long integer;                 /* type with most restrictive alignment */#endif /* MP_LONGLONG_SUPPORT */  long double real;             /* type with most restrictive alignment */  struct  {      union allocaheader *next; /* pointer to next allocaheader */      void *frame;              /* pointer to stack frame */  }  data;}allocaheader;#ifdef __cplusplusextern "C"{#endif /* __cplusplus *//* The stack of allocaheaders that is used to keep track of the details of * (and when to free) memory allocated with alloca() and related functions. */static allocaheader *allocastack;/* Terminate the program after an mpatrol function has been called with an * illegal function type. */staticvoidillegalfunction(char *f, char *s, char *t, unsigned long u){    fputs("fatal error", stderr);    if (s != NULL)        fprintf(stderr, " in %s", s);    if ((t != NULL) && (u != 0))        fprintf(stderr, " in %s line %lu", t, u);    fputc('\n', stderr);    fprintf(stderr, "mpatrol function %s called with illegal function type\n",            f);    fflush(NULL);    exit(EXIT_FAILURE);}/* Round an unsigned integer up to the nearest power of two. */staticunsigned longpoweroftwo(unsigned long n){    unsigned char l;    if ((n == 0) || ((n & (n - 1)) == 0))        return n;    for (l = 0; n > 0; l++, n >>= 1);    return (unsigned long) (2 << (l - 1));}/* Return the system page size. */staticsize_tpagesize(void){    static size_t s;#if TARGET == TARGET_WINDOWS    SYSTEM_INFO i;#endif /* TARGET */    if (s == 0)    {#if TARGET == TARGET_UNIX        /* This call could also be getpagesize() but it is more POSIX-conforming         * to call sysconf().  Unfortunately, SunOS and the BSD systems only         * have getpagesize().         */#if SYSTEM == SYSTEM_FREEBSD || SYSTEM == SYSTEM_NETBSD || \    SYSTEM == SYSTEM_OPENBSD || SYSTEM == SYSTEM_SUNOS        s = getpagesize();#else /* SYSTEM */        s = sysconf(_SC_PAGESIZE);#endif /* SYSTEM */#elif TARGET == TARGET_AMIGA        /* The Amiga has no virtual memory system (at least not supplied with         * AmigaOS), so we return a fixed value here because it doesn't really         * matter what the page size is.         */        s = 4096;#elif TARGET == TARGET_WINDOWS        GetSystemInfo(&i);        s = i.dwPageSize;#elif TARGET == TARGET_NETWARE        s = NXGetPageSize();#else /* TARGET */    /* We just assume that any other operating systems have no virtual     * memory support and so anything we return here is irrelevant.     */    return 1024;#endif /* TARGET */    }    return s;}/* Determine the stack direction on this system. */staticintstackdirection(void *p){    static int d;    unsigned long n;    if (d == 0)    {        n = (unsigned long) &p;        if (p == NULL)            return stackdirection(&n);        else if (&n < (unsigned long *) p)            d = -1;        else            d = 1;    }    return d;}/* Check the alloca allocation stack for any allocations that should be freed. */staticvoidcheckalloca(void *p){    allocaheader *m, *n;    int d;    d = stackdirection(NULL);    for (n = allocastack; n != NULL; n = m)    {        m = n->data.next;        if (((d > 0) && ((char *) n->data.frame > (char *) p + 32)) ||            ((d < 0) && ((char *) n->data.frame + 32 < (char *) p)))        {            free(n);            allocastack = m;        }        else            break;    }}/* The last error encountered by the mpatrol library. */MP_API errortype __mp_errno;/* Initialise the mpatrol library. */MP_APIvoid__mp_init(void){}/* Reinitialise the mpatrol library. */MP_APIvoid__mp_reinit(void){}/* Finalise the mpatrol library. */MP_APIvoid__mp_fini(void){}/* Provide a function which can be used as a breakpoint target in a debugger. */MP_APIvoid__mp_trap(void){}/* Register a finalisation function to be called when __mp_fini() is called. */MP_APIint__mp_atexit(void (*f)(void)){    if (atexit(f) == -1)        return 0;    return 1;}/* Set an mpatrol option after the library has been initialised. */MP_APIunsigned long__mp_setoption(long o, unsigned long v){    return ~0L;}/* Get an mpatrol option after the library has been initialised. */MP_APIint__mp_getoption(long o, unsigned long *v){    return 0;}/* Return the memory header structure. */MP_APIinfohead *__mp_memhead(void){    return NULL;}/* Allocate a new block of memory of a specified size and alignment. */MP_APIvoid *__mp_alloc(size_t l, size_t a, alloctype f, char *s, char *t, unsigned long u,           char *g, size_t h, size_t k){    void *p;    size_t n;    checkalloca(&l);    if (l == 0)        l = 1;    switch (f)    {      case AT_MALLOC:        p = malloc(l);        break;      case AT_CALLOC:        if (p = malloc(l))            memset(p, 0, l);        break;      case AT_MEMALIGN:      case AT_VALLOC:      case AT_PVALLOC:        /* We cannot rely on any system having implementations of memalign(),         * valloc() or pvalloc() and so we must either implement them with         * malloc() or with memalign() if it exists.  For the former         * implementation, this is done by allocating extra space and then         * rounding up the start address of the new allocation to the specified         * alignment.  This means that there is likely to be some space wasted         * for each allocation and the memory allocated by such functions         * cannot be freed with free().  The latter point is also likely to be         * true even if we allocated the memory with memalign().         */        n = pagesize();        if (f == AT_PVALLOC)            l = ((l - 1) & ~(n - 1)) + n;        if ((f == AT_VALLOC) || (f == AT_PVALLOC) || (a > n))            a = n;        else if (a < sizeof(long))            a = sizeof(long);        else            a = poweroftwo(a);#if MP_MEMALIGN_SUPPORT        p = memalign(a, l);#else /* MP_MEMALIGN_SUPPORT */        if (p = malloc(l + a - 1))            p = (void *) ((((unsigned long) p - 1) & ~(a - 1)) + a);#endif /* MP_MEMALIGN_SUPPORT */        break;      case AT_ALLOCA:        p = __mp_xmalloc(l + sizeof(allocaheader), s, t, u, g, h);        ((allocaheader *) p)->data.next = allocastack;        ((allocaheader *) p)->data.frame = (void *) &l;        allocastack = (allocaheader *) p;        p = (char *) p + sizeof(allocaheader);        break;      case AT_XMALLOC:        p = __mp_xmalloc(l, s, t, u, g, h);        break;      case AT_XCALLOC:        p = __mp_xcalloc(l, s, t, u, g, h);        break;      case AT_NEW:      case AT_NEWVEC:        /* This implementation should really call the new handler if it         * has been installed, but for now just abort if no memory can be         * allocated.         */        p = __mp_xmalloc(l, s, t, u, g, h);        break;      default:        illegalfunction("__mp_alloc", s, t, u);        break;    }    return p;}/* Allocate a new block of memory to duplicate a string. */MP_APIchar *__mp_strdup(char *p, size_t l, alloctype f, char *s, char *t, unsigned long u,            size_t k){    char *r;    size_t i;    checkalloca(&p);    if (f == AT_XSTRDUP)        return __mp_xstrdup(p, s, t, u);    i = strlen(p);    if ((f == AT_STRNDUP) || (f == AT_STRNSAVE) || (f == AT_STRNDUPA))    {        if (i > l)            i = l;    }    else if ((f != AT_STRDUP) && (f != AT_STRSAVE) && (f != AT_STRDUPA))        illegalfunction("__mp_strdup", s, t, u);    if ((f == AT_STRDUPA) || (f == AT_STRNDUPA))    {        r = (char *) __mp_xmalloc(i + sizeof(allocaheader) + 1, s, t, u, "char",                                  sizeof(char));        ((allocaheader *) r)->data.next = allocastack;        ((allocaheader *) r)->data.frame = (void *) &p;        allocastack = (allocaheader *) r;        r += sizeof(allocaheader);    }    else        r = (char *) malloc(i + 1);    if (r != NULL)    {        memcpy(r, p, i);        r[i] = '\0';    }    return r;}/* Resize an existing block of memory to a new size and alignment. */MP_APIvoid *__mp_realloc(void *p, size_t l, size_t a, alloctype f, char *s, char *t,             unsigned long u, char *g, size_t h, size_t k){    void *q;    checkalloca(&p);    if (f == AT_XREALLOC)        return __mp_xrealloc(p, l, s, t, u, g, h);    else if ((f != AT_REALLOC) && (f != AT_REALLOCF) && (f != AT_RECALLOC) &&             (f != AT_EXPAND))        illegalfunction("__mp_realloc", s, t, u);    /* There is a major limitation here in that we don't know the size of     * the existing memory allocation.  This means that we can't implement     * recalloc() or expand() properly, and in the latter case means that     * we must always return NULL.  If you have existing implementations     * of these functions on your system then you could make calls to them     * here.     */    if (p == NULL)    {        if (l == 0)            l = 1;        if ((p = malloc(l)) && (f == AT_RECALLOC))            memset(p, 0, l);    }    else if (l == 0)    {        free(p);        p = NULL;    }    else if (f == AT_REALLOCF)    {        if ((q = realloc(p, l)) == NULL)            free(p);        p = q;    }    else if (f != AT_EXPAND)        p = realloc(p, l);    else        p = NULL;    return p;}/* Free an existing block of memory. */MP_APIvoid__mp_free(void *p, alloctype f, char *s, char *t, unsigned long u, size_t k){    checkalloca(&p);    if ((f != AT_FREE) && (f != AT_CFREE) && (f != AT_DEALLOCA) &&        (f != AT_XFREE) && (f != AT_DELETE) && (f != AT_DELETEVEC))        illegalfunction("__mp_free", s, t, u);    if (f != AT_DEALLOCA)        free(p);}/* Set a block of memory to contain a specific byte. */MP_APIvoid *__mp_setmem(void *p, size_t l, unsigned char c, alloctype f, char *s, char *t,            unsigned long u, size_t k){    if ((f != AT_MEMSET) && (f != AT_BZERO))        illegalfunction("__mp_setmem", s, t, u);    return memset(p, (int) c, l);}/* Copy a block of memory from one address to another. */MP_APIvoid *__mp_copymem(void *p, void *q, size_t l, unsigned char c, alloctype f, char *s,             char *t, unsigned long u, size_t k){    void *r;    switch (f)    {      case AT_MEMCCPY:        if (r = memchr(p, (int) c, l))            l = (size_t) ((char *) r - (char *) p) + 1;        memcpy(q, p, l);        if (r != NULL)            q = (char *) q + l;        else            q = NULL;        break;      case AT_MEMCPY:        memcpy(q, p, l);        break;      case AT_MEMMOVE:      case AT_BCOPY:        memmove(q, p, l);        break;      default:        illegalfunction("__mp_copymem", s, t, u);        break;    }    return q;}/* Attempt to locate the position of one block of memory in another block. */MP_APIvoid *__mp_locatemem(void *p, size_t l, void *q, size_t m, alloctype f, char *s,               char *t, unsigned long u, size_t k){    if (f == AT_MEMCHR)        return memchr(p, (int) (m & 0xFF), l);

⌨️ 快捷键说明

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