mad.c

来自「具有IDE功能的编辑器」· C语言 代码 · 共 1,555 行 · 第 1/3 页

C
1,555
字号
/* mad.c memory allocate debugger   Copyright (C) 1996-2000 Paul Sheer   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program 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 General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//********************************************************************//* There is a mad.c and mad.h file that comes with other programs.  *//* This is not the same mad at all. Consider this to be Next        *//* Generation MAD. It is based on the debauch package.              *//********************************************************************/#include "mad.h"#undef malloc#undef calloc#undef strdup#undef free#undef realloc#undef exitint option_debug_malloc = 0;#ifndef DEBUG_MALLOC/* put these here so you don't have to recompiled all sources to turn off mem debugging */void mad_exit (int status){    exit (status);}void *mad_malloc (unsigned desiredsize){    return (void *) malloc (desiredsize);}char *mad_strdup (char *s){    char *p;    p = mad_malloc (strlen (s) + 1);    strcpy (p, s);    return p;}void mad_free (char *p){    free (p);}void *mad_realloc (char *old, unsigned desiredsize){    return (void *) realloc (old, desiredsize);}void *mad_calloc (unsigned num, unsigned size){    return (void *) calloc (num, size);}#else/* include this file with your other sources to get a complete memory leak    reportage with a stack trace for each leak on exit() *//* taken from mad and put into one file by Paul Sheer <psheer /AT/ icon.co.za> *//* * $XConsortium: fmalloc.c /main/7 1996/11/24 17:42:06 rws $ * $XFree86: xc/util/memleak/fmalloc.c,v 3.3 1996/12/31 05:02:25 dawes Exp $ *Copyright (c) 1992  X ConsortiumPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included inall copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THEX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER INAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR INCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.Except as contained in this notice, the name of the X Consortium shall not beused in advertising or otherwise to promote the sale, use or other dealingsin this Software without prior written authorization from the X Consortium. * * Author:  Keith Packard, MIT X Consortium *//* * Leak tracing allocator -- using C lib malloc/free, tracks * all allocations.  When requested, performs a garbage-collection * style mark/sweep on static memory (data and stack), locating * objects referenced therein.  Recursively marks objects. * Sweeps through all allocations, warning of possible violations * (unreferenced allocated, referenced freed etc). */#include    <signal.h>/* interface */void mad_start (void);void check_memory (void);void validate_memory (void);void final_memory_check (void);void exit (int status);void *malloc (unsigned desiredsize);void *calloc (unsigned num, unsigned size);void *realloc (void *old, unsigned desiredsize);void free (void *p);/**********************************************************************************//********* begin getretlinux.c **********************//* * modified from getreti386.c * * Copyright (c) 1995 Jeffrey Hsu * Copyright (c) 1999 Jon A. Christopher */#define get_current_fp(first_local)	((unsigned)&(first_local) + 4)#define prev_fp_from_fp(fp)		*((unsigned *) fp)#define ret_addr_from_fp(fp)		*((unsigned *) (fp+4))static void get_stack_trace (unsigned long *results, int max){    int first_local;    unsigned long fp, ret_addr;    fp = get_current_fp (first_local);    while (fp != 0 && max--) {	ret_addr = ret_addr_from_fp (fp);	*results++ = ret_addr;	fp = prev_fp_from_fp (fp);    }}/********* end getretlinux.c **********************//********* begin stackbottom.c **********************//* * cut and paste from gc 4.4 by Hans-J. Boehm and Alan J. Demers * * Cutter and Paster:  Jeffrey Hsu *//* $XFree86: xc/util/memleak/stackbottom.c,v 3.1 1996/12/31 05:02:27 dawes Exp $ */typedef char *ptr_t;		/* A generic pointer to which we can add        */			/* byte displacements.                          */			/* Preferably identical to caddr_t, if it       */			/* exists.                                      */#ifndef booltypedef int bool;#endif#define VOLATILE volatile#ifndef STACK_GROWS_UP#define STACK_GROWS_DOWN#endiftypedef unsigned long word;#define TRUE 1#if defined(__alpha) || defined(__alpha__)extern __start#define HEURISTIC2_LIMIT ((ptr_t)((word)(&__start) & ~(getpagesize()-1)))#endifvoid GC_noop (){}  /* Some tools to implement HEURISTIC2 */#define MIN_PAGE_SIZE 256	/* Smallest conceivable page size, bytes */#include <setjmp.h>static jmp_buf GC_jmp_buf;static void GC_fault_handler (int sig){    longjmp (GC_jmp_buf, 1);}#ifdef __STDC__typedef void (*handler) (int);#elsetypedef void (*handler) ();#endif    /* Return the first nonaddressible location > p (up) or     */    /* the smallest location q s.t. [q,p] is addressible (!up). */static ptr_t GC_find_limit (ptr_t p, bool up){    static VOLATILE ptr_t result;    /* Needs to be static, since otherwise it may not be    */    /* preserved across the longjmp.  Can safely be         */    /* static since it's only called once, with the         */    /* allocation lock held.                                */    static handler old_segv_handler, old_bus_handler;    /* See above for static declaration.                    */    old_segv_handler = signal (SIGSEGV, GC_fault_handler);#ifdef SIGBUS    old_bus_handler = signal (SIGBUS, GC_fault_handler);#endif    if (setjmp (GC_jmp_buf) == 0) {	result = (ptr_t) (((word) (p))			  & ~(MIN_PAGE_SIZE - 1));	for (;;) {	    if (up) {		result += MIN_PAGE_SIZE;	    } else {		result -= MIN_PAGE_SIZE;	    }	    GC_noop (*result);	}    }    (void) signal (SIGSEGV, old_segv_handler);#ifdef SIGBUS    (void) signal (SIGBUS, old_bus_handler);#endif    if (!up) {	result += MIN_PAGE_SIZE;    }    return (result);}static ptr_t GC_get_stack_base (void){    word dummy;    static ptr_t result;    if (!result) {#ifdef STACK_GROWS_DOWN	result = GC_find_limit ((ptr_t) (&dummy), TRUE);#ifdef HEURISTIC2_LIMIT	if (result > HEURISTIC2_LIMIT && (ptr_t) (&dummy) < HEURISTIC2_LIMIT) {	    result = HEURISTIC2_LIMIT;	}#endif#else	result = GC_find_limit ((ptr_t) (&dummy), FALSE);#ifdef HEURISTIC2_LIMIT	if (result < HEURISTIC2_LIMIT && (ptr_t) (&dummy) > HEURISTIC2_LIMIT) {	    result = HEURISTIC2_LIMIT;	}#endif#endif    }    return (result);}/********* end stackbottom.c **********************//********* begin fmalloc.c **********************/extern char **environ;extern int etext;#define TOP_OF_STACK	GC_get_stack_base()#define BOTTOM_OF_DATA	&etext#define HAS_GET_RETURN_ADDRESS#ifndef FALSE#define FALSE 0#endif#ifndef TRUE#define TRUE 1#endif#if 1#define NO_ATEXIT#else#ifdef X_NOT_POSIX#define NO_ATEXIT#endif#endiftypedef unsigned long mem;#ifdef HAS_GET_RETURN_ADDRESS/* was 16, which is too low for debugging complicated libraries */#define MAX_RETURN_STACK    32#endif#define MAX_FREED_MEMORY    (16*1024*1024)#define ACTIVE_HEAD_MAGIC   0xff1111ff#define ACTIVE_TAIL_MAGIC   0xee2222ee#define ACTIVE_DATA_MAGIC   0xdd3333dd#define FREED_HEAD_MAGIC    0xcc4444cc#define FREED_TAIL_MAGIC    0xbb5555bb#define FREED_DATA_MAGIC    0xcc6666cc/* * the marked fields in each head have two bits - one indicating * references to the head of the block, and one indicating references * to the middle of the block */#define UNREFERENCED	    0#define REFERENCED_HEAD	    1#define REFERENCED_MIDDLE   2typedef struct _head {    struct _head *left, *right;    struct _head *next;    int balance;#ifdef HAS_GET_RETURN_ADDRESS    mem return_stack[MAX_RETURN_STACK];#endif    mem *from;    unsigned long alloc_time;    unsigned long free_time;    int size;    int desiredsize;    int actual_size;    int marked;    int head_magic;} HeadRec, *HeadPtr;typedef struct _tail {    int tail_magic;#if defined(__alpha) || defined(__alpha__)    int tail_pad;#endif} TailRec, *TailPtr;#define header(p)	((HeadPtr) (((char *) (p)) - sizeof (HeadRec)))#define data_for_head(h)	((mem *) ((h) + 1))#define tailer(p)	((TailPtr) (((char *) (p)) + header(p)->size))#define tail_for_head(h)	(tailer(data_for_head(h)))#define round_size	(sizeof (mem))#define round_up(s)	(((s) + round_size - 1) & ~(round_size - 1))#define total_size(s)	((s) + sizeof (HeadRec) + sizeof (TailRec))#define check_init()	if (!end_of_static_memory) end_of_static_memory = sbrk(0)#define block_contains(h,p)  (data_for_head(h) <= (p) && (p) < (mem *) tail_for_head(h))typedef HeadRec tree;typedef mem *tree_data;#define COMPARE_ADDR(a,b,op)	(((unsigned) (a)) op ((unsigned) (b)))#define COMPARE(a,b,op,s)	((!s) ? \			 COMPARE_ADDR(a,b,op) :\			(((a)->actual_size op (b)->actual_size) || \			 ((a)->actual_size == (b)->actual_size && \			  COMPARE_ADDR(a,b,op))))#define LESS_THAN(a,b,s)    COMPARE(a,b,<,s)#define GREATER_THAN(a,b,s) COMPARE(a,b,>,s)#define SEARCH(top,result,p) for (result = top; result;) {\    if ((mem *) (p) < data_for_head(result)) \	result = result->left; \    else if ((mem *) tail_for_head(result) < (mem *) (p)) \	result = result->right; \    else \	break; \}static tree *active_memory, *freed_memory, *dead_memory;static mem *end_of_static_memory;static mem *highest_allocated_memory;static int freed_memory_total;static int freed_memory_count;static int active_memory_total;static int active_memory_count;static int dead_memory_total;static int mad_warn_middle_pointers = 0;static int mad_warn_unreferenced = 0;static int mad_warn_referenced = 0;static int mad_check_always = 0;unsigned long mad_alloc_breakpoint = ~0;unsigned long mad_free_breakpoint = ~0;unsigned long mad_error_time;unsigned long mad_time;static void mark_active_block ();static int tree_insert (tree ** treep, tree * new, int by_size);static int tree_delete (tree ** treep, tree * old, int by_size);static int inited = FALSE;void mad_start (void)/* client programs may call this routine to set error reporting to ignore   memory allocated or freed before the current time */{    mad_error_time = mad_time;}static int output_file = 0;static void output (char *fmt, ...);static void do_init (void){    char *a;    write (2, "initialising MAD\n", 17);    inited = TRUE;    output_file = creat ("mad.out", 0600);    if (output_file < 0) {	perror ("failed to open mad.out for memory debugging\n");	abort ();    }    a = (char *) getenv ("DEBAUCH_WARN_REFERENCED");    if (a)	mad_warn_referenced = (int) atoi (a);    a = (char *) getenv ("DEBAUCH_ERROR_TIME");    if (a)	mad_error_time = (long) atol (a);    a = (char *) getenv ("DEBAUCH_WARN_UNREFERENCED");    if (a)	mad_warn_unreferenced = (int) atoi (a);    a = (char *) getenv ("DEBAUCH_WARN_MIDDLE_POINTERS");    if (a)	mad_warn_middle_pointers = (long) atoi (a);    a = (char *) getenv ("DEBAUCH_ALLOC_BREAKPOINT");    if (a)	mad_alloc_breakpoint = (long) atol (a);    a = (char *) getenv ("DEBAUCH_FREE_BREAKPOINT");    if (a)	mad_free_breakpoint = (long) atol (a);    a = (char *) getenv ("DEBAUCH_CHECK_ALWAYS");    if (a)	mad_check_always = (int) atoi (a);    if (option_debug_malloc >= 2)	mad_check_always = 1;#ifndef NO_ATEXIT    atexit (final_memory_check);#endif}#ifdef HAS_GET_RETURN_ADDRESSstatic void print_return_stack (char *m, mem * ra){    int i;    output ("   %s:", m);    for (i = 0; i < MAX_RETURN_STACK && ra[i]; i++)	output (" 0x%lx", ra[i]);    output ("\n");}#endifstatic void mem_error (char *s, HeadPtr h, int ourRet){#if 0    mem *ra;    int i;#endif    /* Silence messages from memory allocated or freed before       mad_error_time */    if (mad_error_time) {	if (h) {	    if (h->alloc_time && h->alloc_time < mad_error_time)		return;	    if (h->free_time && h->free_time < mad_error_time)		return;	} else {

⌨️ 快捷键说明

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