Skip to content

Commit c7f0a9c

Browse files
committed
Fix memory leak in subclasses when freeing classext
We don't decrement the super and module subclasses count for iclasses that are having their classext replaced. This causes the reference count to be incorrect and leak memory. The following script demonstrates the memory leak: module Foo refine(Object) do define_method(:<=) {} end end class Bar include Comparable end With RUBY_FREE_AT_EXIT and ASAN, we can see many memory leaks, including: Direct leak of 16 byte(s) in 1 object(s) allocated from: #0 0x599f715adca2 in calloc (miniruby+0x64ca2) #1 0x599f716bd779 in calloc1 gc/default/default.c:1495:12 #2 0x599f716d1370 in rb_gc_impl_calloc gc/default/default.c:8216:5 #3 0x599f716b8ab1 in ruby_xcalloc_body gc.c:5221:12 #4 0x599f716b269c in ruby_xcalloc gc.c:5215:34 #5 0x599f715eab23 in class_alloc0 class.c:790:22 #6 0x599f715e4bec in class_alloc class.c:836:12 #7 0x599f715e60c9 in module_new class.c:1693:17 #8 0x599f715e60a2 in rb_module_new class.c:1701:12 #9 0x599f715e6303 in rb_define_module class.c:1733:14 #10 0x599f715ebc5f in Init_Comparable compar.c:315:22 #11 0x599f716e35f5 in rb_call_inits inits.c:32:5 #12 0x599f7169cbfd in ruby_setup eval.c:88:9 #13 0x599f7169cdac in ruby_init eval.c:100:17 #14 0x599f715b0fa9 in rb_main main.c:41:5 #15 0x599f715b0f59 in main main.c:62:12 #16 0x739b2f02a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #17 0x739b2f02a28a in __libc_start_main csu/../csu/libc-start.c:360:3 #18 0x599f7157c424 in _start (miniruby+0x33424)
1 parent f054131 commit c7f0a9c

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

class.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -695,14 +695,14 @@ rb_class_classext_free_subclasses(rb_classext_t *ext, VALUE klass, bool replacin
695695
rb_box_subclasses_ref_dec(anchor->box_subclasses);
696696
xfree(anchor);
697697

698-
if (!replacing && RCLASSEXT_BOX_SUPER_SUBCLASSES(ext)) {
698+
if (RCLASSEXT_BOX_SUPER_SUBCLASSES(ext)) {
699699
rb_box_subclasses_t *box_sub = RCLASSEXT_BOX_SUPER_SUBCLASSES(ext);
700-
remove_class_from_subclasses(box_sub->tbl, box_id, klass);
700+
if (!replacing) remove_class_from_subclasses(box_sub->tbl, box_id, klass);
701701
rb_box_subclasses_ref_dec(box_sub);
702702
}
703-
if (!replacing && RCLASSEXT_BOX_MODULE_SUBCLASSES(ext)) {
703+
if (RCLASSEXT_BOX_MODULE_SUBCLASSES(ext)) {
704704
rb_box_subclasses_t *box_sub = RCLASSEXT_BOX_MODULE_SUBCLASSES(ext);
705-
remove_class_from_subclasses(box_sub->tbl, box_id, klass);
705+
if (!replacing) remove_class_from_subclasses(box_sub->tbl, box_id, klass);
706706
rb_box_subclasses_ref_dec(box_sub);
707707
}
708708
}

0 commit comments

Comments
 (0)