ruby-changes:38569
From: nobu <ko1@a...>
Date: Wed, 27 May 2015 17:03:05 +0900 (JST)
Subject: [ruby-changes:38569] nobu:r50650 (trunk): bigdecimal.c: wrapper object before alloc
nobu 2015-05-27 17:02:28 +0900 (Wed, 27 May 2015) New Revision: 50650 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=50650 Log: bigdecimal.c: wrapper object before alloc * ext/bigdecimal/bigdecimal.c (VpNewRbClass): make wrapper object before result structs allocation and manage refcount for each elements to get rid of potential memory leak. * ext/bigdecimal/bigdecimal.c (BigDecimal_global_new): ditto. Modified files: trunk/ext/bigdecimal/bigdecimal.c trunk/test/bigdecimal/test_bigdecimal.rb Index: ext/bigdecimal/bigdecimal.c =================================================================== --- ext/bigdecimal/bigdecimal.c (revision 50649) +++ ext/bigdecimal/bigdecimal.c (revision 50650) @@ -598,17 +598,17 @@ GetPositiveInt(VALUE v) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L598 VP_EXPORT Real * VpNewRbClass(size_t mx, const char *str, VALUE klass) { + VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0); Real *pv = VpAlloc(mx,str); - pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv); + RTYPEDDATA_DATA(obj) = pv; + pv->obj = obj; return pv; } VP_EXPORT Real * VpCreateRbObject(size_t mx, const char *str) { - Real *pv = VpAlloc(mx,str); - pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv); - return pv; + return VpNewRbClass(mx, str, rb_cBigDecimal); } #define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT)) @@ -2595,11 +2595,13 @@ BigDecimal_global_new(int argc, VALUE *a https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2595 { ENTER(1); Real *pv; + VALUE obj; + obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0); GUARD_OBJ(pv, BigDecimal_new(argc, argv)); if (ToValue(pv)) pv = VpCopy(NULL, pv); - pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv); - return pv->obj; + RTYPEDDATA_DATA(obj) = pv; + return pv->obj = obj; } /* call-seq: Index: test/bigdecimal/test_bigdecimal.rb =================================================================== --- test/bigdecimal/test_bigdecimal.rb (revision 50649) +++ test/bigdecimal/test_bigdecimal.rb (revision 50650) @@ -1552,4 +1552,31 @@ class TestBigDecimal < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/bigdecimal/test_bigdecimal.rb#L1552 Thread.current.keys.to_s EOS end + + def assert_no_memory_leak(code, *rest, **opt) + code = "5.times {1_000.times {begin #{code}; rescue NoMemoryError; end; GC.start}} if b" + super(["-rbigdecimal"], + "b = BigDecimal('10'); b.nil?; " \ + "GC.add_stress_to_class(BigDecimal); "\ + "#{code}", code, *rest, rss: true, **opt) + end + + if EnvUtil.gc_stress_to_class? + def test_no_memory_leak_allocate + assert_no_memory_leak("BigDecimal.allocate") + end + + def test_no_memory_leak_initialize + assert_no_memory_leak("BigDecimal.new") + end + + def test_no_memory_leak_global_new + assert_no_memory_leak("BigDecimal('10')") + assert_no_memory_leak("BigDecimal(b)") + end + + def test_no_memory_leak_create + assert_no_memory_leak("b + 10") + end + end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/