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

📄 dmalloc.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. *//* * Dmalloc-compatible interface.  Implements Dmalloc functions using * mpatrol.  Dmalloc is copyright (C) 1992-2001 Gray Watson. */#include "config.h"#include "dmalloc.h"#include <stdio.h>#include <ctype.h>#include <time.h>#if MP_IDENT_SUPPORT#ident "$Id: dmalloc.c,v 1.16 2002/01/08 20:05:10 graeme Exp $"#else /* MP_IDENT_SUPPORT */static MP_CONST MP_VOLATILE char *dmalloc_id = "$Id: dmalloc.c,v 1.16 2002/01/08 20:05:10 graeme Exp $";#endif /* MP_IDENT_SUPPORT *//* Specify whether to prefix every log message produced by * __mpt_dmallocmessage() and __mpt_dmallocvmessage() with the current * time in numerical form and/or string form.  The current event number * can also be logged as well. */#define LOG_TIME_NUMBER     1#define LOG_CTIME_STRING    0#define LOG_ITERATION_COUNT 1/* The escape characters that should be given special consideration in * bytestring(). */#define ESCAPE_CHARS   "\\\a\b\f\n\r\t\v"#define ESCAPE_REPLACE "\\abfnrtv"/* The structure used to store information about each debugging token * recognised by the Dmalloc library. */typedef struct tokeninfo{    char *longname;     /* long token name */    char *shortname;    /* short token name */    unsigned long flag; /* associated flag */}tokeninfo;/* The structure used to pass information to the callback function from * __mp_iterate() when __mpt_dmalloclogchanged() is called. */typedef struct listinfo{    unsigned long kcount; /* known count */    unsigned long ktotal; /* known total */    unsigned long ucount; /* unknown count */    unsigned long utotal; /* unknown total */    int unfreed : 1;      /* log unfreed allocations */    int freed : 1;        /* log freed allocations */    int details : 1;      /* log pointer details */}listinfo;#ifdef __cplusplusextern "C"{#endif /* __cplusplus *//* The table containing all of the recognised debugging tokens with their * associated flags. */static tokeninfo tokens[] ={    {"none", "nil", 0},    {"log-stats", "lst", DMALLOC_LOG_STATS},    {"log-non-free", "lnf", DMALLOC_LOG_NONFREE},    {"log-known", "lkn", DMALLOC_LOG_KNOWN},    {"log-trans", "ltr", DMALLOC_LOG_TRANS},    {"log-admin", "lad", DMALLOC_LOG_ADMIN},    {"log-blocks", "lbl", DMALLOC_LOG_BLOCKS},    {"log-bad-space", "lbs", DMALLOC_LOG_BAD_SPACE},    {"log-nonfree-space", "lns", DMALLOC_LOG_NONFREE_SPACE},    {"check-fence", "cfe", DMALLOC_CHECK_FENCE},    {"check-heap", "che", DMALLOC_CHECK_HEAP},    {"check-lists", "cli", DMALLOC_CHECK_LISTS},    {"check-blank", "cbl", DMALLOC_CHECK_BLANK},    {"check-funcs", "cfu", DMALLOC_CHECK_FUNCS},    {"force-linear", "fli", DMALLOC_FORCE_LINEAR},    {"catch-signals", "csi", DMALLOC_CATCH_SIGNALS},    {"log-elapsed-time", "let", DMALLOC_LOG_ELAPSED_TIME},    {"log-current-time", "lct", DMALLOC_LOG_CURRENT_TIME},    {"realloc-copy", "rco", DMALLOC_REALLOC_COPY},    {"free-blank", "fbl", DMALLOC_FREE_BLANK},    {"error-abort", "eab", DMALLOC_ERROR_ABORT},    {"alloc-blank", "abl", DMALLOC_ALLOC_BLANK},    {"heap-check-map", "hcm", DMALLOC_HEAP_CHECK_MAP},    {"print-messages", "pme", DMALLOC_PRINT_MESSAGES},    {"catch-null", "cnu", DMALLOC_CATCH_NULL},    {"never-reuse", "nre", DMALLOC_NEVER_REUSE},    {"allow-free-null", "afn", DMALLOC_ALLOW_FREE_NULL},    {"error-dump", "edu", DMALLOC_ERROR_DUMP},    {NULL, NULL, 0}};/* Indicates if this module has been initialised. */static int malloc_initialised;/* The time at which this module was initialised. */static time_t malloc_time;/* The library debug flags. */static unsigned long malloc_flags;/* The point at which to start checking the heap and the frequency at which * to check it. */static unsigned long malloc_start, malloc_interval;/* The pointer to the callback function registered with __mpt_dmalloctrack(). */static dmalloc_track_t malloc_tracker;/* The previous mpatrol prologue and epilogue handlers. */static __mp_prologuehandler old_prologue;static __mp_epiloguehandler old_epilogue;/* The pointer, size and alignment obtained each time our prologue function is * called.  This is then used by our epilogue function, but we don't need to * worry about nested calls to the prologue function since the mpatrol library * guarantees that it will never occur, even when there are multiple threads. */static void *malloc_pointer;static size_t malloc_size;static size_t malloc_align;/* The global variables which control the behaviour of the library and are * part of the Dmalloc library interface.  The last two are intended for use * within a debugger. */char *dmalloc_logpath;void *dmalloc_address;unsigned long dmalloc_address_count;/* Read any library options from the DMALLOC_OPTIONS environment variable. */staticvoidreadoptions(void){    static char b[1024];    tokeninfo *i;    char *p, *s, *t;    if (((s = getenv("DMALLOC_OPTIONS")) == NULL) || (*s == '\0'))        return;    strncpy(b, s, sizeof(b) - 1);    b[sizeof(b) - 1] = '\0';    for (s = t = b; t != NULL; s = t + 1)    {        if (t = strchr(s, ','))            *t = '\0';        if (*s == '\0')            continue;        if ((strncmp(s, "addr", 4) == 0) && (s[4] == '='))        {            if (p = strchr(s + 5, ':'))                *p = '\0';            dmalloc_address = (void *) strtoul(s + 5, NULL, 16);            if (p != NULL)                dmalloc_address_count = strtoul(p + 1, NULL, 10);        }        else if ((strncmp(s, "debug", 5) == 0) && (s[5] == '='))            malloc_flags = strtoul(s + 6, NULL, 16);        else if ((strncmp(s, "inter", 5) == 0) && (s[5] == '='))        {            if ((malloc_interval = strtoul(s + 6, NULL, 10)) == 0)                malloc_interval = 1;        }        else if ((strncmp(s, "log", 3) == 0) && (s[3] == '='))            dmalloc_logpath = s + 4;        else if ((strncmp(s, "start", 5) == 0) && (s[5] == '='))            if (strchr(s + 6, ':') == NULL)                malloc_start = strtoul(s + 6, NULL, 10);            else                malloc_start = 0;        else            for (i = tokens; i->longname != NULL; i++)                if ((strcmp(s, i->longname) == 0) ||                    (strcmp(s, i->shortname) == 0))                {                    malloc_flags |= i->flag;                    break;                }    }}/* Map the Dmalloc options to mpatrol options. */staticvoidsetoptions(void){    unsigned long v;    if (dmalloc_logpath != NULL)    {        __mp_setoption(MP_OPT_LOGFILE, (unsigned long) dmalloc_logpath);        dmalloc_logpath = NULL;    }    v = MP_FLG_SHOWFREE;    if (malloc_flags & DMALLOC_LOG_STATS)        __mp_setoption(MP_OPT_SETFLAGS, v);    else        __mp_setoption(MP_OPT_UNSETFLAGS, v);    v = MP_FLG_SHOWUNFREED;    if (malloc_flags & DMALLOC_LOG_NONFREE)        __mp_setoption(MP_OPT_SETFLAGS, v);    else        __mp_setoption(MP_OPT_UNSETFLAGS, v);    v = MP_FLG_LOGALLOCS | MP_FLG_LOGREALLOCS | MP_FLG_LOGFREES;    if (malloc_flags & DMALLOC_LOG_TRANS)        __mp_setoption(MP_OPT_SETFLAGS, v);    else        __mp_setoption(MP_OPT_UNSETFLAGS, v);    if (malloc_flags & DMALLOC_CHECK_FENCE)    {        if (!__mp_getoption(MP_OPT_OFLOWSIZE, &v) || (v == 0))            v = sizeof(void *);    }    else        v = 0;    __mp_setoption(MP_OPT_OFLOWSIZE, v);    if (malloc_flags & DMALLOC_CHECK_HEAP)    {        v = (unsigned long) -1;        __mp_setoption(MP_OPT_CHECKLOWER, malloc_start);    }    else    {        v = 0;        __mp_setoption(MP_OPT_CHECKLOWER, 0);    }    __mp_setoption(MP_OPT_CHECKUPPER, v);    __mp_setoption(MP_OPT_CHECKFREQ, malloc_interval);    v = MP_FLG_SAFESIGNALS;    if (malloc_flags & DMALLOC_CATCH_SIGNALS)        __mp_setoption(MP_OPT_SETFLAGS, v);    else        __mp_setoption(MP_OPT_UNSETFLAGS, v);    v = MP_FLG_PRESERVE;    if (malloc_flags & DMALLOC_FREE_BLANK)        __mp_setoption(MP_OPT_UNSETFLAGS, v);    else        __mp_setoption(MP_OPT_SETFLAGS, v);    v = MP_FLG_SHOWMAP;    if (malloc_flags & DMALLOC_HEAP_CHECK_MAP)        __mp_setoption(MP_OPT_SETFLAGS, v);    else        __mp_setoption(MP_OPT_UNSETFLAGS, v);    if (malloc_flags & DMALLOC_NEVER_REUSE)        v = ~0L;    else        v = 0;    __mp_setoption(MP_OPT_NOFREE, v);    v = MP_FLG_CHECKFREES;    if (malloc_flags & DMALLOC_ALLOW_FREE_NULL)        __mp_setoption(MP_OPT_UNSETFLAGS, v);    else        __mp_setoption(MP_OPT_SETFLAGS, v);}/* Record the pointer, size and alignment for later processing by the epilogue * function and possibly also call the old prologue function if one was * installed. */staticvoidprologue(MP_CONST void *p, size_t l, size_t m, MP_CONST char *s,         MP_CONST char *t, unsigned long u, MP_CONST void *a){    if (old_prologue != NULL)        old_prologue(p, l, m, s, t, u, a);    malloc_pointer = (void *) p;    malloc_size = l;    malloc_align = m;}/* Call the tracker function with any relevant details if one has been * registered and possibly also call the old epilogue function if one was * installed. */staticvoidepilogue(MP_CONST void *p, MP_CONST char *s, MP_CONST char *t, unsigned long u,         MP_CONST void *a){    size_t l;    if (dmalloc_logpath != NULL)    {        __mp_setoption(MP_OPT_LOGFILE, (unsigned long) dmalloc_logpath);        dmalloc_logpath = NULL;    }    if (malloc_tracker != NULL)    {        if (malloc_pointer == (void *) -1)            malloc_tracker(t, u, DMALLOC_FUNC_MALLOC, malloc_size, malloc_align,                           NULL, p);        else if (malloc_size == (size_t) -1)            malloc_tracker(t, u, DMALLOC_FUNC_FREE, 0, 0, malloc_pointer, NULL);        else if (malloc_size == (size_t) -2)        {            if (malloc_pointer == NULL)                l = 0;            else                l = strlen((char *) malloc_pointer) + 1;            malloc_tracker(t, u, DMALLOC_FUNC_STRDUP, l, malloc_align, NULL, p);        }        else if (malloc_pointer == NULL)            malloc_tracker(t, u, DMALLOC_FUNC_MALLOC, malloc_size, malloc_align,                           NULL, p);        else if (malloc_size == 0)            malloc_tracker(t, u, DMALLOC_FUNC_FREE, 0, 0, malloc_pointer, NULL);        else            malloc_tracker(t, u, DMALLOC_FUNC_REALLOC, malloc_size,                           malloc_align, malloc_pointer, p);    }    if (old_epilogue != NULL)        old_epilogue(p, s, t, u, a);}/* Convert the bytes in a memory allocation to human-readable form. */staticchar *bytestring(char *b, size_t s, char *p, size_t l){    char *t;    size_t i, n;    for (i = n = 0; (i < s) && (i < l); i++)        if (p[i] == '\0')        {            b[n++] = '\\';            b[n++] = '0';            if ((i < s - 1) && (i < l - 1))            {                b[n++] = '0';                b[n++] = '0';            }        }        else if (t = strchr(ESCAPE_CHARS, p[i]))        {            b[n++] = '\\';            b[n++] = ESCAPE_REPLACE[t - ESCAPE_CHARS];        }        else if (!isprint(p[i]))        {

⌨️ 快捷键说明

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