GC_INNER GC_bool GC_check_leaked(ptr_t base) { size_t i; size_t obj_sz; word *p; if ( # if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH) (*(word *)base & 1) != 0 && # endif GC_has_other_debug_info(base) >= 0) return TRUE; /* object has leaked */ /* Validate freed object's content. */ p = (word *)(base + sizeof(oh)); obj_sz = BYTES_TO_WORDS(HDR(base)->hb_sz - sizeof(oh)); for (i = 0; i < obj_sz; ++i) if (p[i] != GC_FREED_MEM_MARKER) { GC_set_mark_bit(base); /* do not reclaim it in this cycle */ GC_add_smashed((ptr_t)(&p[i])); /* alter-after-free detected */ break; /* don't report any other smashed locations in the object */ } return FALSE; /* GC_debug_free() has been called */ }
/*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; } }
/* Avoid GC_apply_to_each_object for performance reasons. */ STATIC void GC_check_heap_block(struct hblk *hbp, word dummy GC_ATTR_UNUSED) { struct hblkhdr * hhdr = HDR(hbp); word sz = hhdr -> hb_sz; word bit_no; char *p, *plim; p = hbp->hb_body; if (sz > MAXOBJBYTES) { plim = p; } else { plim = hbp->hb_body + HBLKSIZE - sz; } /* go through all words in block */ for (bit_no = 0; (word)p <= (word)plim; bit_no += MARK_BIT_OFFSET(sz), p += sz) { 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); } } }