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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50650 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
2df5bb9ac1
commit
bdf07741f3
@ -598,17 +598,17 @@ GetPositiveInt(VALUE v)
|
|||||||
VP_EXPORT Real *
|
VP_EXPORT Real *
|
||||||
VpNewRbClass(size_t mx, const char *str, VALUE klass)
|
VpNewRbClass(size_t mx, const char *str, VALUE klass)
|
||||||
{
|
{
|
||||||
|
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
||||||
Real *pv = VpAlloc(mx,str);
|
Real *pv = VpAlloc(mx,str);
|
||||||
pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv);
|
RTYPEDDATA_DATA(obj) = pv;
|
||||||
|
pv->obj = obj;
|
||||||
return pv;
|
return pv;
|
||||||
}
|
}
|
||||||
|
|
||||||
VP_EXPORT Real *
|
VP_EXPORT Real *
|
||||||
VpCreateRbObject(size_t mx, const char *str)
|
VpCreateRbObject(size_t mx, const char *str)
|
||||||
{
|
{
|
||||||
Real *pv = VpAlloc(mx,str);
|
return VpNewRbClass(mx, str, rb_cBigDecimal);
|
||||||
pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
|
|
||||||
return pv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
|
#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);
|
ENTER(1);
|
||||||
Real *pv;
|
Real *pv;
|
||||||
|
VALUE obj;
|
||||||
|
|
||||||
|
obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
|
||||||
GUARD_OBJ(pv, BigDecimal_new(argc, argv));
|
GUARD_OBJ(pv, BigDecimal_new(argc, argv));
|
||||||
if (ToValue(pv)) pv = VpCopy(NULL, pv);
|
if (ToValue(pv)) pv = VpCopy(NULL, pv);
|
||||||
pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
|
RTYPEDDATA_DATA(obj) = pv;
|
||||||
return pv->obj;
|
return pv->obj = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call-seq:
|
/* call-seq:
|
||||||
|
@ -1552,4 +1552,31 @@ class TestBigDecimal < Test::Unit::TestCase
|
|||||||
Thread.current.keys.to_s
|
Thread.current.keys.to_s
|
||||||
EOS
|
EOS
|
||||||
end
|
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
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user