From f0d08d11dcd404f3146c0d71d6ff743bbc6e7193 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 29 Jun 2023 09:21:11 -0400 Subject: Fix memory leak when copying ST tables st_copy allocates a st_table, which is not needed for hashes since it is allocated by VWA and embedded, so this causes a memory leak. The following script demonstrates the issue: ```ruby 20.times do 100_000.times do {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9} end puts `ps -o rss= -p #{$$}` end ``` --- hash.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'hash.c') diff --git a/hash.c b/hash.c index a74db258e4..a779c6f218 100644 --- a/hash.c +++ b/hash.c @@ -1482,7 +1482,9 @@ hash_copy(VALUE ret, VALUE hash) else { HASH_ASSERT(sizeof(st_table) <= sizeof(ar_table)); - RHASH_ST_TABLE_SET(ret, st_copy(RHASH_ST_TABLE(hash))); + RHASH_SET_ST_FLAG(ret); + st_replace(RHASH_ST_TABLE(ret), RHASH_ST_TABLE(hash)); + rb_gc_writebarrier_remember(ret); } return ret; @@ -1776,7 +1778,8 @@ rb_hash_s_create(int argc, VALUE *argv, VALUE klass) } else { hash = hash_alloc(klass); - hash_copy(hash, tmp); + if (!RHASH_EMPTY_P(tmp)) + hash_copy(hash, tmp); return hash; } } -- cgit v1.2.3