[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]