📄 dbg_mlc.c
字号:
if (clobbered != 0) { if (((oh *)base) -> oh_sz == GC_size(base)) { GC_err_printf( "GC_debug_free: found previously deallocated (?) object at "); } else { GC_err_printf("GC_debug_free: found smashed location at "); } GC_print_smashed_obj(p, clobbered); } /* Invalidate size */ ((oh *)base) -> oh_sz = GC_size(base);# endif /* SHORT_DBG_HDRS */ } if (GC_find_leak) { GC_free(base); } else { hdr * hhdr = HDR(p); GC_bool uncollectable = FALSE; if (hhdr -> hb_obj_kind == UNCOLLECTABLE) { uncollectable = TRUE; }# ifdef ATOMIC_UNCOLLECTABLE if (hhdr -> hb_obj_kind == AUNCOLLECTABLE) { uncollectable = TRUE; }# endif if (uncollectable) { GC_free(base); } else { size_t i; size_t obj_sz = BYTES_TO_WORDS(hhdr -> hb_sz - sizeof(oh)); for (i = 0; i < obj_sz; ++i) ((word *)p)[i] = 0xdeadbeef; GC_ASSERT((word *)p + i == (word *)(base + hhdr -> hb_sz)); } } /* !GC_find_leak */}#ifdef THREADSextern void GC_free_inner(void * p);/* Used internally; we assume it's called correctly. */void GC_debug_free_inner(void * p){ GC_free_inner(GC_base(p));}#endifvoid * GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS){ void * base = GC_base(p); ptr_t clobbered; void * result; size_t copy_sz = lb; size_t old_sz; hdr * hhdr; if (p == 0) return(GC_debug_malloc(lb, OPT_RA s, i)); if (base == 0) { GC_err_printf("Attempt to reallocate invalid pointer %p\n", p); ABORT("realloc(invalid pointer)"); } if ((ptr_t)p - (ptr_t)base != sizeof(oh)) { GC_err_printf( "GC_debug_realloc called on pointer %p wo debugging info\n", p); return(GC_realloc(p, lb)); } hhdr = HDR(base); switch (hhdr -> hb_obj_kind) {# ifdef STUBBORN_ALLOC case STUBBORN: result = GC_debug_malloc_stubborn(lb, OPT_RA s, i); break;# endif case NORMAL: result = GC_debug_malloc(lb, OPT_RA s, i); break; case PTRFREE: result = GC_debug_malloc_atomic(lb, OPT_RA s, i); break; case UNCOLLECTABLE: result = GC_debug_malloc_uncollectable(lb, OPT_RA s, i); break;# ifdef ATOMIC_UNCOLLECTABLE case AUNCOLLECTABLE: result = GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i); break;# endif default: GC_err_printf("GC_debug_realloc: encountered bad kind\n"); ABORT("bad kind"); }# ifdef SHORT_DBG_HDRS old_sz = GC_size(base) - sizeof(oh);# else clobbered = GC_check_annotated_obj((oh *)base); if (clobbered != 0) { GC_err_printf("GC_debug_realloc: found smashed location at "); GC_print_smashed_obj(p, clobbered); } old_sz = ((oh *)base) -> oh_sz;# endif if (old_sz < copy_sz) copy_sz = old_sz; if (result == 0) return(0); BCOPY(p, result, copy_sz); GC_debug_free(p); return(result);}#ifndef SHORT_DBG_HDRS/* List of smashed objects. We defer printing these, since we can't *//* always print them nicely with the allocation lock held. *//* We put them here instead of in GC_arrays, since it may be useful to *//* be able to look at them with the debugger. */#define MAX_SMASHED 20ptr_t GC_smashed[MAX_SMASHED];unsigned GC_n_smashed = 0;void GC_add_smashed(ptr_t smashed){ GC_ASSERT(GC_is_marked(GC_base(smashed))); GC_smashed[GC_n_smashed] = smashed; if (GC_n_smashed < MAX_SMASHED - 1) ++GC_n_smashed; /* In case of overflow, we keep the first MAX_SMASHED-1 */ /* entries plus the last one. */ GC_have_errors = TRUE;}/* Print all objects on the list. Clear the list. */void GC_print_all_smashed_proc(void){ unsigned i; GC_ASSERT(I_DONT_HOLD_LOCK()); if (GC_n_smashed == 0) return; GC_err_printf("GC_check_heap_block: found smashed heap objects:\n"); for (i = 0; i < GC_n_smashed; ++i) { GC_print_smashed_obj(GC_base(GC_smashed[i]), GC_smashed[i]); GC_smashed[i] = 0; } GC_n_smashed = 0;}/* Check all marked objects in the given block for validity *//* Avoid GC_apply_to_each_object for performance reasons. *//*ARGSUSED*/void GC_check_heap_block(struct hblk *hbp, word dummy){ struct hblkhdr * hhdr = HDR(hbp); size_t sz = hhdr -> hb_sz; size_t bit_no; char *p, *plim; p = hbp->hb_body; bit_no = 0; if (sz > MAXOBJBYTES) { plim = p; } else { plim = hbp->hb_body + HBLKSIZE - sz; } /* go through all words in block */ while( p <= plim ) { if( mark_bit_from_hdr(hhdr, bit_no) && GC_HAS_DEBUG_INFO((ptr_t)p)) { ptr_t clobbered = GC_check_annotated_obj((oh *)p); if (clobbered != 0) GC_add_smashed(clobbered); } bit_no += MARK_BIT_OFFSET(sz); p += sz; }}/* This assumes that all accessible objects are marked, and that *//* I hold the allocation lock. Normally called by collector. */void GC_check_heap_proc(void){# ifndef SMALL_CONFIG /* Ignore gcc no effect warning on the following. */ GC_STATIC_ASSERT((sizeof(oh) & (GRANULE_BYTES - 1)) == 0); /* FIXME: Should we check for twice that alignment? */# endif GC_apply_to_all_blocks(GC_check_heap_block, (word)0);}#endif /* !SHORT_DBG_HDRS */struct closure { GC_finalization_proc cl_fn; void * cl_data;};void * GC_make_closure(GC_finalization_proc fn, void * data){ struct closure * result =# ifdef DBG_HDRS_ALL (struct closure *) GC_debug_malloc(sizeof (struct closure), GC_EXTRAS);# else (struct closure *) GC_malloc(sizeof (struct closure));# endif result -> cl_fn = fn; result -> cl_data = data; return((void *)result);}void GC_debug_invoke_finalizer(void * obj, void * data){ register struct closure * cl = (struct closure *) data; (*(cl -> cl_fn))((void *)((char *)obj + sizeof(oh)), cl -> cl_data);} /* Set ofn and ocd to reflect the values we got back. */static void store_old (void *obj, GC_finalization_proc my_old_fn, struct closure *my_old_cd, GC_finalization_proc *ofn, void **ocd){ if (0 != my_old_fn) { if (my_old_fn != GC_debug_invoke_finalizer) { GC_err_printf("Debuggable object at %p had non-debug finalizer.\n", obj); /* This should probably be fatal. */ } else { if (ofn) *ofn = my_old_cd -> cl_fn; if (ocd) *ocd = my_old_cd -> cl_data; } } else { if (ofn) *ofn = 0; if (ocd) *ocd = 0; }}void GC_debug_register_finalizer(void * obj, GC_finalization_proc fn, void * cd, GC_finalization_proc *ofn, void * *ocd){ GC_finalization_proc my_old_fn; void * my_old_cd; ptr_t base = GC_base(obj); if (0 == base) return; if ((ptr_t)obj - base != sizeof(oh)) { GC_err_printf( "GC_debug_register_finalizer called with non-base-pointer %p\n", obj); } if (0 == fn) { GC_register_finalizer(base, 0, 0, &my_old_fn, &my_old_cd); } else { GC_register_finalizer(base, GC_debug_invoke_finalizer, GC_make_closure(fn,cd), &my_old_fn, &my_old_cd); } store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);}void GC_debug_register_finalizer_no_order (void * obj, GC_finalization_proc fn, void * cd, GC_finalization_proc *ofn, void * *ocd){ GC_finalization_proc my_old_fn; void * my_old_cd; ptr_t base = GC_base(obj); if (0 == base) return; if ((ptr_t)obj - base != sizeof(oh)) { GC_err_printf( "GC_debug_register_finalizer_no_order called with " "non-base-pointer %p\n", obj); } if (0 == fn) { GC_register_finalizer_no_order(base, 0, 0, &my_old_fn, &my_old_cd); } else { GC_register_finalizer_no_order(base, GC_debug_invoke_finalizer, GC_make_closure(fn,cd), &my_old_fn, &my_old_cd); } store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);}void GC_debug_register_finalizer_unreachable (void * obj, GC_finalization_proc fn, void * cd, GC_finalization_proc *ofn, void * *ocd){ GC_finalization_proc my_old_fn; void * my_old_cd; ptr_t base = GC_base(obj); if (0 == base) return; if ((ptr_t)obj - base != sizeof(oh)) { GC_err_printf( "GC_debug_register_finalizer_unreachable called with " "non-base-pointer %p\n", obj); } if (0 == fn) { GC_register_finalizer_unreachable(base, 0, 0, &my_old_fn, &my_old_cd); } else { GC_register_finalizer_unreachable(base, GC_debug_invoke_finalizer, GC_make_closure(fn,cd), &my_old_fn, &my_old_cd); } store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);}void GC_debug_register_finalizer_ignore_self (void * obj, GC_finalization_proc fn, void * cd, GC_finalization_proc *ofn, void * *ocd){ GC_finalization_proc my_old_fn; void * my_old_cd; ptr_t base = GC_base(obj); if (0 == base) return; if ((ptr_t)obj - base != sizeof(oh)) { GC_err_printf( "GC_debug_register_finalizer_ignore_self called with " "non-base-pointer %p\n", obj); } if (0 == fn) { GC_register_finalizer_ignore_self(base, 0, 0, &my_old_fn, &my_old_cd); } else { GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer, GC_make_closure(fn,cd), &my_old_fn, &my_old_cd); } store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);}#ifdef GC_ADD_CALLER# define RA GC_RETURN_ADDR,#else# define RA#endifvoid * GC_debug_malloc_replacement(size_t lb){ return GC_debug_malloc(lb, RA "unknown", 0);}void * GC_debug_realloc_replacement(void *p, size_t lb){ return GC_debug_realloc(p, lb, RA "unknown", 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -