From d5a774dd920488036646942935cd1a213d5ea258 Mon Sep 17 00:00:00 2001 From: Laurent Sansonetti Date: Thu, 19 May 2011 17:43:37 -0700 Subject: [PATCH] add rb_print_memory_objects() debug function --- HACKING.rdoc | 7 +++++++ gc.c | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/HACKING.rdoc b/HACKING.rdoc index 2d0d3db60..73d88086a 100644 --- a/HACKING.rdoc +++ b/HACKING.rdoc @@ -166,3 +166,10 @@ The following environment variables might help you debug easy bugs. * To symbolize a Ruby address (named as ??) in the backtrace: (gdb) p (void)rb_symbolicate(
) + +* To print the addresses of all memory objects of a given minimum size (useful + when debugging memory leaks): + (gdb) p (void)rb_print_memory_objects() + +* To print the GC references of a given memory object: + (gdb) info gc-references
diff --git a/gc.c b/gc.c index 32648c10b..47a7b9281 100644 --- a/gc.c +++ b/gc.c @@ -561,7 +561,7 @@ rb_objc_yield_classes(VALUE of) static void rb_objc_recorder(task_t task, void *context, unsigned type_mask, - vm_range_t *ranges, unsigned range_count) + vm_range_t *ranges, unsigned range_count) { struct rb_objc_recorder_context *ctx; vm_range_t *r, *end; @@ -1057,3 +1057,35 @@ rb_gc_register_address(VALUE *slot) { rb_global_variable(slot); } + +static void +print_memory_object(task_t task, void *context, unsigned type_mask, + vm_range_t *ranges, unsigned range_count) +{ + const size_t min_size = *(size_t *)context; + for (vm_range_t *r = ranges, *end = ranges + range_count; r < end; r++) { + const size_t size = auto_zone_size(__auto_zone, (void *)r->address); + if (size >= min_size) { + printf("address %p size %ld layout type ", + (void *)r->address, size); + switch (auto_zone_get_layout_type(__auto_zone, + (void *)r->address)) { + case AUTO_OBJECT: + printf("object (class %s)\n", + class_getName(object_getClass((void *)r->address))); + break; + default: + printf("memory\n"); + break; + } + } + } +} + +void +rb_print_memory_objects(size_t min_size) +{ + (((malloc_zone_t *)__auto_zone)->introspect->enumerator)(mach_task_self(), + (void *)&min_size, MALLOC_PTR_IN_USE_RANGE_TYPE, + (vm_address_t)__auto_zone, NULL, print_memory_object); +}