summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorPeter Zhu <[email protected]>2024-01-03 15:59:37 -0500
committerPeter Zhu <[email protected]>2024-01-04 11:25:31 -0500
commit6c252912af4981f016a9abdb4c1689307a4f1d2f (patch)
tree29aaa7c2ba9770f9a99058bc73d2a84857287bd6 /hash.c
parent542011ff6895f77204349ddfae7dcfb476e116df (diff)
Memory leak when duplicating identhash
[Bug #20145] Before this commit, both copy_compare_by_id and hash_copy will create a copy of the ST table, so the ST table created in copy_compare_by_id will be leaked. h = { 1 => 2 }.compare_by_identity 10.times do 1_000_000.times do h.select { false } end puts `ps -o rss= -p #{$$}` end Before: 110736 204352 300272 395520 460704 476736 542000 604704 682624 770528 After: 15504 16048 16144 16256 16320 16320 16752 16752 16752 16752
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/hash.c b/hash.c
index 51f8f85d63..97b5b52c10 100644
--- a/hash.c
+++ b/hash.c
@@ -1558,7 +1558,15 @@ hash_copy(VALUE ret, VALUE hash)
static VALUE
hash_dup_with_compare_by_id(VALUE hash)
{
- return hash_copy(copy_compare_by_id(rb_hash_new(), hash), hash);
+ VALUE dup = hash_alloc_flags(rb_cHash, 0, Qnil, RHASH_ST_TABLE_P(hash));
+ if (RHASH_ST_TABLE_P(hash)) {
+ RHASH_SET_ST_FLAG(dup);
+ }
+ else {
+ RHASH_UNSET_ST_FLAG(dup);
+ }
+
+ return hash_copy(dup, hash);
}
static VALUE