mad.c

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

C
1,555
字号
	    if (mad_time < mad_error_time)		return;	}    }    if (h) {	output ("%s 0x%08lx, size %d (from 0x%lx) AllocTime: %ld FreeTime: %ld\t",		s, (unsigned long) data_for_head (h), h->desiredsize, (unsigned long) h->from,		h->alloc_time, h->free_time);#ifdef HAS_GET_RETURN_ADDRESS	print_return_stack ("Saved return stack", h->return_stack);#endif	if (!ourRet)	    output ("\n");    } else	output ("%s\n", s);#ifdef HAS_GET_RETURN_ADDRESS    if (ourRet) {	mem return_stack[MAX_RETURN_STACK];	memset (return_stack, 0, sizeof (return_stack));	if (h)	    output ("%s 0x%08lx; now at stack address:\t", s, data_for_head (h));	else	    output ("%s 0x%08lx; now at stack address:\t", s, 0);	get_stack_trace (return_stack, MAX_RETURN_STACK);	print_return_stack ("Current return stack", return_stack);	output ("\n");#ifdef DEBUG_MALLOC_EXCLUDE_EXTERNAL	(void) mad_exit (1);#else	exit (1);#endif    }#endif}static void mark_memory_region (mem * low, mem * high){    mem **start = (mem **) low, **end = (mem **) high;    mem *p;    while (start < end) {	p = *start;	if (end_of_static_memory <= p && p < highest_allocated_memory)	    mark_active_block (p, (mem *) start);	start++;    }}static void mark_active_block (mem * p, mem * from){    HeadPtr h;    int marked;    int oldMarked;    SEARCH (active_memory, h, p)	if (h) {	marked = REFERENCED_HEAD;	if (p != data_for_head (h))	    marked = REFERENCED_MIDDLE;	oldMarked = h->marked;	if (!(oldMarked & marked)) {	    h->marked |= marked;	    h->from = from;	    if (!oldMarked)		mark_memory_region (data_for_head (h), (mem *) tail_for_head (h));	}	return;    }    SEARCH (freed_memory, h, p)	if (h) {	marked = REFERENCED_HEAD;	if (p != data_for_head (h))	    marked = REFERENCED_MIDDLE;	if (!(h->marked & marked)) {	    h->marked |= marked;	    h->from = from;	}	return;    }}static void clear_tree (tree * t){    if (!t)	return;    clear_tree (t->left);    t->marked = 0;    t->from = 0;    clear_tree (t->right);}static void sweep_active_tree (tree * t){    if (!t)	return;    sweep_active_tree (t->left);    if (!t->marked) {	if (mad_warn_unreferenced)	    mem_error ("Unreferenced allocated", t, FALSE);    } else if (!(t->marked & REFERENCED_HEAD))	mem_error ("Referenced allocated middle", t, FALSE);    sweep_active_tree (t->right);}static void report_leaks_in_tree (tree * t){    if (!t)	return;    report_leaks_in_tree (t->left);    mem_error ("Leaked Memory", t, FALSE);    report_leaks_in_tree (t->right);}/* * run a thread through the tree at the same time * - the thread runs  * * root -> left_child ... -> right_child ... -> null */static tree *sweep_freed_tree (tree * t){    tree *left_last, *right_last;    if (!t)	return 0;    left_last = sweep_freed_tree (t->left);    if (t->marked) {	if (t->marked & REFERENCED_HEAD) {	    if (mad_warn_referenced)		mem_error ("Referenced freed base", t, FALSE);	} else if (mad_warn_middle_pointers)	    mem_error ("Referenced freed middle", t, FALSE);    }    right_last = sweep_freed_tree (t->right);    if (t->left)	t->next = t->left;    else	t->next = t->right;    if (left_last)	left_last->next = t->right;    if (!right_last)	right_last = left_last;    if (!right_last)	right_last = t;    return right_last;}static void sweep_freed_memory (void){    tree *t, *n;    int count, shouldCount;    (void) sweep_freed_tree (freed_memory);    count = 0;    shouldCount = freed_memory_count;    for (t = freed_memory; t; t = n) {	n = t->next;	count++;	if (!t->marked) {	    (void) tree_delete (&freed_memory, t, FALSE);	    freed_memory_total -= t->desiredsize;	    freed_memory_count--;	    tree_insert (&dead_memory, t, TRUE);	}    }    if (count != shouldCount)	abort ();}static int validate_tree (tree * head, mem head_magic, mem tail_magic, mem body_magic, char *mesg,			  int check_only){    TailPtr tail;    mem *p;    int i, r = 0;    if (!head)	return r;    r |= validate_tree (head->left, head_magic, tail_magic, body_magic, mesg, check_only);    tail = tail_for_head (head);    if (head->head_magic != head_magic) {	if (!check_only)	    mem_error (mesg, head, FALSE);	r = 1;    }    if (tail->tail_magic != tail_magic) {	if (!check_only)	    mem_error (mesg, head, FALSE);	r = 1;    }    if (body_magic) {	i = head->size / sizeof (mem);	p = data_for_head (head);	while (i--) {	    if (*p++ != body_magic) {		if (!check_only)		    mem_error (mesg, head, FALSE);		r = 1;	    }	}    }    r |= validate_tree (head->right, head_magic, tail_magic, body_magic, mesg, check_only);    return r;}static int validate_active_memory (int check_only){    return validate_tree (active_memory, ACTIVE_HEAD_MAGIC, ACTIVE_TAIL_MAGIC,			  0, "Store outside of active memory", check_only);}static int validate_freed_memory (int check_only){    return validate_tree (freed_memory, FREED_HEAD_MAGIC, FREED_TAIL_MAGIC,			  FREED_DATA_MAGIC, "Store into freed memory", check_only);}static void add_active_block (HeadPtr h){    TailPtr t = tail_for_head (h);    mem *p;    int i;    tree_insert (&active_memory, h, FALSE);    if ((mem *) t > highest_allocated_memory)	highest_allocated_memory = (mem *) t;    /*     * Breakpoint position - assign mad_alloc_breakpoint with     * debugger and set a breakpoint in the conditional clause below     */    if (mad_time == mad_alloc_breakpoint)	h->head_magic = ACTIVE_HEAD_MAGIC;	/* set breakpoint here */    h->alloc_time = mad_time++;    h->head_magic = ACTIVE_HEAD_MAGIC;    t->tail_magic = ACTIVE_TAIL_MAGIC;    i = h->size / sizeof (mem);    p = data_for_head (h);    while (i--)	*p++ = ACTIVE_DATA_MAGIC;    active_memory_total += h->desiredsize;    active_memory_count++;}static void remove_active_block (HeadPtr h){    active_memory_total -= h->desiredsize;    active_memory_count--;    tree_delete (&active_memory, h, FALSE);}static void add_freed_block (HeadPtr h){    TailPtr t = tail_for_head (h);    int i;    mem *p;    tree_insert (&freed_memory, h, FALSE);    /*     * Breakpoint position - assign mad_free_breakpoint with     * debugger and set a breakpoint in the conditional clause below     */    if (mad_time == mad_free_breakpoint)	h->head_magic = FREED_HEAD_MAGIC;	/* set breakpoint here */    h->free_time = mad_time++;    h->head_magic = FREED_HEAD_MAGIC;    t->tail_magic = FREED_TAIL_MAGIC;    i = h->size / sizeof (mem);    p = data_for_head (h);    while (i--)	*p++ = FREED_DATA_MAGIC;    freed_memory_total += h->desiredsize;    freed_memory_count++;    /* GC if we've got piles of unused memory */    if (freed_memory_total - dead_memory_total >= MAX_FREED_MEMORY)	validate_memory ();}/* * Entry points: * *  check_memory ()		--	Verifies heap *  final_memory_check ()	--	Verifies heap, reporting any leaks *  malloc (size)		--	Allocates memory *  free (old)			--	Deallocates memory *  realloc (old, size)		--	Allocate, copy, free *  calloc (num, size_per)	--	Allocate and zero */void validate_memory (void){    int r = 0;    r |= validate_active_memory (1);    r |= validate_freed_memory (1);    if (r)	mem_error ("Corrupted memory", (HeadPtr) 0, TRUE);}void check_memory (void){    mem foo;    output ("\nCheckMemory\n");    output ("%d bytes active memory in %d allocations\n", active_memory_total, active_memory_count);    output ("%d bytes freed memory held from %d allocations\n", freed_memory_total,	    freed_memory_count);    validate_active_memory (0);    validate_freed_memory (0);    clear_tree (active_memory);    clear_tree (freed_memory);    mark_memory_region ((mem *) BOTTOM_OF_DATA, (mem *) end_of_static_memory);    mark_memory_region ((mem *) & foo, (mem *) TOP_OF_STACK);    sweep_active_tree (active_memory);    sweep_freed_memory ();    output ("%d bytes freed memory still held from %d allocations\n",	    freed_memory_total, freed_memory_count);    dead_memory_total = freed_memory_total;    output ("check_memory done\n");}void final_memory_check (void){    output ("\nFinalMemoryCheck\n");    check_memory ();    output ("\nReportLeaks\n");    report_leaks_in_tree (active_memory);    output ("\nReportLeaks done\n");    output ("final_memory_check done\n");}/* * Allocator interface -- malloc and free (others in separate files) */#define CORE_CHUNK  16384static char *core;static unsigned core_left;static unsigned total_core_used;#ifdef DEBUG_MALLOC_EXCLUDE_EXTERNALvoid mad_exit (int status)#elsevoid exit (int status)#endif{#ifdef DEBUG_MALLOC_EXCLUDE_EXTERNAL    if (!option_debug_malloc)	exit (status);#endif    signal (SIGPIPE, SIG_IGN);    signal (SIGINT, SIG_IGN);    signal (SIGTERM, SIG_IGN);    signal (SIGQUIT, SIG_IGN);    {	long pid;	char buf[1024];	char s[65536], **p, *q;	char *l[] = { "exec 1>&2",	    "echo \"Note that your program must have been compiled\"",	    "echo \"with -O0 -g to enable memory leak stack traces\"",	    "EXEPID=%ld",	    "OUT=mad.out",	    "LINES=mad.lines",	    "SED=mad.sed",	    "ADDRS=mad.addrs",	    "GDBCMD=mad.gdb",	    "trap \"rm -f $SED $LINES $ADDRS $OUT $GDBCMD\" 0",	    "sed 's;Saved;\\",	    "  ;' $OUT | sed 's;Current;\\",	    "  ;' | grep 'return stack:' | tr ' ' '\\012' | grep 0x | sort -u > $ADDRS",	    "echo \"attach $EXEPID\" > $GDBCMD",	    "sed 's;^;info line *;' $ADDRS >> $GDBCMD",	    "echo quit >> $GDBCMD",	    "gdb /proc/$EXEPID/exe -x $GDBCMD | grep 'address' |",	    "  sed 's/No line number information available for/Line ?? of \"???\" starts at/' |",	    "  sed 's/(gdb) //' > $LINES",	    "paste $ADDRS $LINES | awk '{ printf(\"s;%%s;%%s:%%s (%%s) %%s;\\n\", $1, $5, $3, $1, $10) }' > $SED",	    "echo \"s;\\\";;g\" >> $SED",	    "grep -v Saved $OUT | grep -v Current | sed 's;^$;;' | uniq",	    "sort -t\\t +1 $OUT | grep \"return stack\" | uniq -c -f5 |",	    "  sed 's;Current;\\",	    "  ;' | sed 's;Saved;\\",	    "  ;' | sed 's/^\\ */ /' | ",	    "awk '/return stack/ { printf (\"\\treturn stack:\\n\");",	    "  for (i = 3; i <= NF; i++)",	    "  printf (\"\\t\\t%%s\\n\", $i); }",	    "  /^\\ *[0-9]/  { print }' |",	    "sed -f $SED ", 0	};	pid = getpid ();	memset (s, 0, sizeof (s));	for (q = s, p = l; *p; p++) {	    sprintf (q, *p, pid);	    q += strlen (q);	    *q++ = '\n';	}	final_memory_check ();	if (!fork ()) {	    if (!fork ()) {		execl ("/bin/sh", "/bin/sh", "-c", s, 0);		_exit (1);	    }	    _exit (0);	}	while (!stat ("mad.out", buf))	    sleep (1);	_exit (status);    }}static char *morecore (unsigned size){    unsigned alloc_size;    char *alloc, *newcore;    if (core_left < size) {	alloc_size = (size + CORE_CHUNK - 1) & ~(CORE_CHUNK - 1);	newcore = (char *) sbrk (alloc_size);	if (((int) newcore) == -1)	    return 0;	core = newcore;	core_left = alloc_size;	total_core_used += alloc_size;    }    alloc = core;    core += size;    core_left -= size;    return alloc;}#ifdef DEBUG_MALLOC_EXCLUDE_EXTERNALvoid *mad_malloc (unsigned desiredsize)#elsevoid *malloc (unsigned desiredsize)#endif{    unsigned size;    unsigned totalsize;    HeadPtr h;#ifdef DEBUG_MALLOC_EXCLUDE_EXTERNAL    if (!option_debug_malloc)	return malloc (desiredsize);#endif    if (!inited)	do_init ();    if (!end_of_static_memory)	end_of_static_memory = (mem *) sbrk (0);    if (mad_check_always)	validate_memory ();    size = round_up (desiredsize);    totalsize = total_size (size);    h = dead_memory;    while (h) {	if (h->actual_size == size)	    /* h is just right */	    break;	/* h just won't do; we need something bigger */	else if (size > h->actual_size) {	    h = h->right;	    if (!h)		break;	    /* h will work, but something smaller would be less wasteful */	} else if (h->left == 0 || h->left->actual_size << size)	    /* there are no suitable smaller blocks; h will have to do */	    break;	/* now we're sure there's a better fit */	h = h->left;    }    if (h) {	tree_delete (&dead_memory, h, TRUE);    } else {	h = (HeadPtr) morecore (totalsize);	if (!h)	    return 0;	h->actual_size = size;    }    h->desiredsize = desiredsize;    h->size = size;#ifdef HAS_GET_RETURN_ADDRESS    get_stack_trace (h->return_stack, MAX_RETURN_STACK);#endif    add_active_block (h);    return (void *) data_for_head (h);}#ifdef DEBUG_MALLOC_EXCLUDE_EXTERNALchar *mad_strdup (char *s)#elsechar *strdup (char *s)#endif{    char *p;#ifdef DEBUG_MALLOC_EXCLUDE_EXTERNAL    p = mad_malloc (strlen (s) + 1);#else    p = malloc (strlen (s) + 1);#endif    strcpy (p, s);    return p;}

⌨️ 快捷键说明

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