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

📄 inter.c

📁 debug source code under unix platform.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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. *//* * Library interface.  This module defines the visible interface for the * mpatrol library.  It also defines replacement functions for the GNU * Checker tool, which adds code to check all reads from and writes to * memory when the user's code is compiled with the -fcheck-memory-usage * option in the GNU compiler. */#include "inter.h"#include "diag.h"#include "machine.h"#if MP_THREADS_SUPPORT#include "mutex.h"#endif /* MP_THREADS_SUPPORT */#if (TARGET == TARGET_AMIGA && defined(__GNUC__)) || \    (TARGET == TARGET_WINDOWS && !defined(__GNUC__))#include "sbrk.h"#endif /* TARGET && __GNUC__ */#include "option.h"#include "version.h"#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <time.h>#if TARGET == TARGET_UNIX#include <unistd.h>#endif /* TARGET */#if MP_IDENT_SUPPORT#ident "$Id: inter.c,v 1.156 2002/01/08 20:13:59 graeme Exp $"#else /* MP_IDENT_SUPPORT */static MP_CONST MP_VOLATILE char *inter_id = "$Id: inter.c,v 1.156 2002/01/08 20:13:59 graeme Exp $";#endif /* MP_IDENT_SUPPORT */#ifdef __cplusplusextern "C"{#endif /* __cplusplus */#if MP_INUSE_SUPPORTint _Inuse_init(unsigned long, int);void _Inuse_close(void);#endif /* MP_INUSE_SUPPORT *//* The memory header structure used by the library to hold all of its data * and settings. */static infohead memhead;#if TARGET == TARGET_UNIX#if SYSTEM == SYSTEM_LINUX/* This contains a pointer to the environment variables for a process.  If * it is not set up yet then we must use sbrk() to allocate all memory since * we can't initialise mpatrol until the environment variable can be read. */extern char **__environ;#elif SYSTEM == SYSTEM_TRU64/* The exception support library on Tru64 always allocates some memory from * the heap in order to initialise the code address range tables.  We need * to ensure that we don't initialise mpatrol before this otherwise stack * unwinding will fail, so we check to ensure that the table has been set up * before we proceed.  We also need to ensure that we don't try to unwind the * stack before the mpatrol library is initialised so we use a flag for this. */static int init_flag;extern void *__exc_crd_list_head;#endif /* SYSTEM */#elif TARGET == TARGET_WINDOWS && !defined(__GNUC__)/* These are global variables used by the Microsoft C run-time library to * indicate initialisation of the environment variables, the exit function * table and the streams buffers respectively.  The run-time library calls * malloc() and related functions to set these up so we cannot initialise * the mpatrol library until all of these have been set up.  Instead, we * will call sbrk() to allocate enough memory for these as they appear, but * we cannot record anything about these allocations. */extern int __env_initialized;extern void *__onexitbegin;extern void **__piob;#endif /* TARGET && __GNUC__ *//* Determine if the C run-time library is initialised. */#if TARGET == TARGET_UNIX#if SYSTEM == SYSTEM_LINUX#define crt_initialised() (__environ)#elif SYSTEM == SYSTEM_TRU64#define crt_initialised() (__exc_crd_list_head && init_flag)#else /* SYSTEM */#define crt_initialised() (1)#endif /* SYSTEM */#elif TARGET == TARGET_WINDOWS#ifndef __GNUC__#define crt_initialised() (__env_initialized && __onexitbegin && __piob)#else /* __GNUC__ */#define crt_initialised() (1)#endif /* __GNUC__ */#endif /* TARGET */#if MP_INIT_SUPPORT/* On systems with .init and .fini sections we can plant calls to initialise * the mpatrol mutexes and data structures before main() is called and also * to terminate the mpatrol library after exit() is called.  However, we need * to refer to a symbol within the machine module so that we can drag in the * contents of the .init and .fini sections when the mpatrol library is built * as an archive library. */static int *initsection = &__mp_initsection;#elif SYSTEM == SYSTEM_TRU64/* Tru64 has an interesting feature in that any global functions whose names * begin with __init_* and __fini_* will be called before and after main() * respectively.  Note that we don't define __INIT_* and __FINI_* functions * since they are reserved for the system. */void__init_mpatrol(void){#if MP_THREADS_SUPPORT    __mp_initmutexes();#endif /* MP_THREADS_SUPPORT */    __mp_init();    init_flag = 1;}#if !MP_USE_ATEXITvoid__fini_mpatrol(void){    __mp_fini();}#endif /* MP_USE_ATEXIT */#elif defined(__GNUC__)/* The GNU C compiler allows us to indicate that a function is a constructor * which should be called before main() or that a function is a destructor * that should be called at or after exit().  However, these get entered into * the .ctors and .dtors sections which means that the final link must also * be performed by the GNU C compiler. */static void initlibrary(void) __attribute__((__constructor__));staticvoidinitlibrary(void){#if MP_THREADS_SUPPORT    __mp_initmutexes();#endif /* MP_THREADS_SUPPORT */    __mp_init();}#if !MP_USE_ATEXITstatic void finilibrary(void) __attribute__((__destructor__));staticvoidfinilibrary(void){    __mp_fini();}#endif /* MP_USE_ATEXIT */#elif defined(__cplusplus)/* C++ provides a way to initialise the mpatrol library before main() is * called and terminate it after exit() is called.  Note that if the C++ * compiler uses a special section for calling functions before main() that * is not recognised by the system tools then the C++ compiler must also be * used to perform the final link. */static struct initlibrary{    initlibrary()    {#if MP_THREADS_SUPPORT        __mp_initmutexes();#endif /* MP_THREADS_SUPPORT */        __mp_init();    }#if !MP_USE_ATEXIT    ~initlibrary()    {        __mp_fini();    }#endif /* MP_USE_ATEXIT */}meminit;#endif /* __cplusplus *//* Save the current signal handlers and set them to ignore.  Also lock the * library data structures if we are thread-safe. */staticvoidsavesignals(void){#if MP_THREADS_SUPPORT    __mp_lockmutex(MT_MAIN);#endif /* MP_THREADS_SUPPORT */    /* Only perform this step if we are not doing a recursive call.     */    if (memhead.recur++ == 0)    {        if (!memhead.init)            __mp_initsignals(&memhead.signals);        if (memhead.flags & FLG_SAFESIGNALS)            __mp_savesignals(&memhead.signals);    }}/* Restore the previous signal handlers.  Also unlock the library data * structures if we are thread-safe. */staticvoidrestoresignals(void){    /* Only perform this step if we are not doing a recursive call.     */    if (--memhead.recur == 0)        __mp_restoresignals(&memhead.signals);#if MP_THREADS_SUPPORT    __mp_unlockmutex(MT_MAIN);#endif /* MP_THREADS_SUPPORT */}/* Check the validity of all memory blocks, but only if the allocation count * is within range and the event count is a multiple of the heap checking * frequency. */staticvoidcheckheap(loginfo *v, unsigned long n){    unsigned long l;    /* If the lower and upper bounds are zero then we never need to check     * the heap.     */    if ((l = memhead.lrange) || (memhead.urange != 0))    {        if (l == (unsigned long) -1)            l = 0;        if ((l <= n) && (n <= memhead.urange) &&            ((memhead.check == 1) || (memhead.event % memhead.check == 0)))            __mp_checkinfo(&memhead, v);    }}/* Check the alloca allocation stack for any allocations that should be freed. */staticvoidcheckalloca(loginfo *i, int f){    allocanode *n, *p;#if MP_FULLSTACK    addrnode *a, *b;    stackcompare r;#endif /* MP_FULLSTACK */    alloctype t;    int c;    if (memhead.fini || (memhead.astack.size == 0))        return;#if MP_FULLSTACK    /* Create the address nodes for the current call.  This is not necessarily     * an efficient way of doing call stack comparisons if the alloca allocation     * stack does not contain many outstanding entries, but on some platforms     * call stack traversal is an expensive business.     */    if (!(memhead.flags & FLG_NOPROTECT))        __mp_protectaddrs(&memhead.addr, MA_READWRITE);    a = __mp_getaddrs(&memhead.addr, i->stack);    if (!(memhead.flags & FLG_NOPROTECT))        __mp_protectaddrs(&memhead.addr, MA_READONLY);#endif /* MP_FULLSTACK */    for (n = (allocanode *) memhead.astack.head;         p = (allocanode *) n->node.next; n = p)    {        c = 0;        if (f == 1)            c = 1;#if MP_FULLSTACK        /* We need to compare the call stacks of the two calling functions in         * order to see if we can free the allocation.  Currently, this just         * involves ensuring that the call stacks are different or that the         * current call stack is shallower than that which made the original         * allocation.  In theory we could also free the allocation if the         * current call stack was deeper and the initial addresses differ, but         * that would involve a lot more calculations.         */        else        {            b = (addrnode *) n->data.frame;            if ((b->data.next != NULL) && (a->data.next != NULL) &&                (((r = __mp_compareaddrs(b->data.next, a->data.next)) ==                  SC_DIFFERENT) || (r == SC_SHALLOWER)))                c = 1;        }#else /* MP_FULLSTACK */        /* We need to add an arbitrary number of bytes to the address of the         * local variable in order to be completely safe, since the current         * call may differ by one stack frame if the entry to the mpatrol         * library was via a macro defined in mpatrol.h rather than a function         * defined in malloc.c, or vice versa.  Unfortunately, this means that         * we are going to be unable to free the allocation at the first         * available point when it goes out of scope.         */        else if (memhead.alloc.heap.memory.stackdir < 0)        {            /* The stack grows down so we must ensure that the current local             * variable pointer occupies a higher address than that which             * made the original allocation if we are to free the allocation.             */            if ((char *) n->data.frame + 256 < (char *) &i->stack->frame)                c = 1;        }        else        {            /* The stack grows up so we must ensure that the current local             * variable pointer occupies a lower address than that which             * made the original allocation if we are to free the allocation.             */            if ((char *) n->data.frame > (char *) &i->stack->frame + 256)                c = 1;        }#endif /* MP_FULLSTACK */        if (c == 1)        {            if (memhead.prologue && (memhead.recur == 1))                memhead.prologue(n->block, (size_t) -1, 0, i->func, i->file,                                 i->line, i->stack->addr);            memhead.event++;            t = i->type;            i->type = AT_ALLOCA;            __mp_freememory(&memhead, n->block, i);            i->type = t;            if (memhead.epilogue && (memhead.recur == 1))                memhead.epilogue((void *) -1, i->func, i->file, i->line,                                 i->stack->addr);        }    }#if MP_FULLSTACK    /* Free the address nodes for the current call.  They may well have to be     * generated again but that can't be guaranteed.     */    if (a != NULL)    {        if (!(memhead.flags & FLG_NOPROTECT))            __mp_protectaddrs(&memhead.addr, MA_READWRITE);        __mp_freeaddrs(&memhead.addr, a);        if (!(memhead.flags & FLG_NOPROTECT))            __mp_protectaddrs(&memhead.addr, MA_READONLY);    }#endif /* MP_FULLSTACK */}/* Deal with anything that needs to be done with marked memory allocations * at program termination. */staticvoidfinishmarked(void){    allocnode *n;    infonode *m;    treenode *t;    unsigned long d;    int p;#if MP_THREADS_SUPPORT    d = __mp_threadid();#else /* MP_THREADS_SUPPORT */    d = 0;#endif /* MP_THREADS_SUPPORT */    if (memhead.flags & FLG_NOPROTECT)        p = -1;    else        p = 0;    for (t = __mp_minimum(memhead.alloc.atree.root); t != NULL;         t = __mp_successor(t))    {        n = (allocnode *) ((char *) t - offsetof(allocnode, tnode));        m = (infonode *) n->info;        if (m->data.flags & FLG_MARKED)        {            if ((p == 0) && (m->data.flags & (FLG_PROFILED | FLG_TRACED)))            {                __mp_protectinfo(&memhead, MA_READWRITE);                p = 1;            }            if (m->data.flags & FLG_PROFILED)                __mp_profilefree(&memhead.prof, n->size, m,                                 !(memhead.flags & FLG_NOPROTECT));            if (m->data.flags & FLG_TRACED)                __mp_tracefree(&memhead.trace, m->data.alloc, d, NULL, NULL, 0);        }    }    if (p == 1)        __mp_protectinfo(&memhead, MA_READONLY);}/* The last error encountered by the mpatrol library. */MP_API errortype __mp_errno;/* Initialise the mpatrol library. */MP_APIvoid

⌨️ 快捷键说明

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