mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Fix memory leak at the same named alias [Bug #18516]
When aliasing a method to the same name method, set a separate bit flag on that method definition, instead of the reference count increment. Although this kind of alias has no actual effect at runtime, is used as the hack to suppress the method re-definition warning.
This commit is contained in:
parent
7ff1bf3178
commit
e89d80702b
Notes:
git
2022-01-27 15:46:41 +09:00
3 changed files with 27 additions and 1 deletions
1
method.h
1
method.h
|
@ -181,6 +181,7 @@ struct rb_method_definition_struct {
|
|||
unsigned int iseq_overload: 1;
|
||||
int alias_count : 27;
|
||||
int complemented_count : 28;
|
||||
unsigned int no_redef_warning: 1;
|
||||
|
||||
union {
|
||||
rb_method_iseq_t iseq;
|
||||
|
|
|
@ -264,4 +264,22 @@ class TestAlias < Test::Unit::TestCase
|
|||
end
|
||||
end;
|
||||
end
|
||||
|
||||
def test_alias_memory_leak
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", rss: true)
|
||||
begin;
|
||||
class A
|
||||
500.times do
|
||||
1000.times do |i|
|
||||
define_method(:"foo_#{i}") {}
|
||||
|
||||
alias :"foo_#{i}" :"foo_#{i}"
|
||||
|
||||
remove_method :"foo_#{i}"
|
||||
end
|
||||
GC.start
|
||||
end
|
||||
end
|
||||
end;
|
||||
end
|
||||
end
|
||||
|
|
|
@ -856,6 +856,7 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil
|
|||
if (RTEST(ruby_verbose) &&
|
||||
type != VM_METHOD_TYPE_UNDEF &&
|
||||
(old_def->alias_count == 0) &&
|
||||
(!old_def->no_redef_warning) &&
|
||||
!make_refined &&
|
||||
old_def->type != VM_METHOD_TYPE_UNDEF &&
|
||||
old_def->type != VM_METHOD_TYPE_ZSUPER &&
|
||||
|
@ -1086,7 +1087,13 @@ method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me,
|
|||
rb_method_visibility_t visi, VALUE defined_class)
|
||||
{
|
||||
rb_method_entry_t *newme = rb_method_entry_make(klass, mid, defined_class, visi,
|
||||
me->def->type, method_definition_addref(me->def), 0, NULL);
|
||||
me->def->type, me->def, 0, NULL);
|
||||
if (newme == me) {
|
||||
me->def->no_redef_warning = TRUE;
|
||||
}
|
||||
else {
|
||||
method_definition_addref(me->def);
|
||||
}
|
||||
method_added(klass, mid);
|
||||
return newme;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue