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 + -
显示快捷键?