summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/bigdecimal/bigdecimal.c14
-rw-r--r--test/bigdecimal/test_bigdecimal.rb27
2 files changed, 35 insertions, 6 deletions
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index ce06e65e3f..7d498724fe 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -598,17 +598,17 @@ GetPositiveInt(VALUE v)
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 *argv, VALUE self)
{
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:
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
index 042d11da0f..ad48d70799 100644
--- a/test/bigdecimal/test_bigdecimal.rb
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -1552,4 +1552,31 @@ class TestBigDecimal < Test::Unit::TestCase
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