From: gfx Date: Sat, 12 Jun 2010 03:58:49 +0000 (+0900) Subject: Fix possible memory leaks, which occurs when constructor components throw errors. X-Git-Tag: 0.61~4 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMouse.git;a=commitdiff_plain;h=fcdc12ac0d67969cf79745b062fd706ae56c8b92 Fix possible memory leaks, which occurs when constructor components throw errors. --- diff --git a/xs-src/Mouse.xs b/xs-src/Mouse.xs index 8033635..19d98c6 100644 --- a/xs-src/Mouse.xs +++ b/xs-src/Mouse.xs @@ -571,26 +571,28 @@ PPCODE: } } -SV* +void new_object(SV* meta, ...) CODE: { AV* const xc = mouse_get_xc(aTHX_ meta); HV* const args = mouse_buildargs(aTHX_ meta, NULL, ax, items); + SV* object; - RETVAL = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc)); - mouse_class_initialize_object(aTHX_ meta, RETVAL, args, FALSE); - mouse_buildall(aTHX_ xc, RETVAL, sv_2mortal(newRV_inc((SV*)args))); /* BUILDALL */ + object = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc)); + mouse_class_initialize_object(aTHX_ meta, object, args, FALSE); + mouse_buildall(aTHX_ xc, object, sv_2mortal(newRV_inc((SV*)args))); /* BUILDALL */ + ST(0) = object; /* because object is mortal, we should return it as is */ + XSRETURN(1); } -OUTPUT: - RETVAL -SV* +void clone_object(SV* meta, SV* object, ...) CODE: { AV* const xc = mouse_get_xc(aTHX_ meta); HV* const args = mouse_buildargs(aTHX_ meta, NULL, ax + 1, items - 1); + SV* proto; if(!mouse_is_an_instance_of(aTHX_ MOUSE_xc_stash(xc), object)) { mouse_throw_error(meta, object, @@ -598,12 +600,11 @@ CODE: mcall0(meta, mouse_name), object); } - RETVAL = mouse_instance_clone(aTHX_ object); - mouse_class_initialize_object(aTHX_ meta, RETVAL, args, TRUE); + proto = mouse_instance_clone(aTHX_ object); + mouse_class_initialize_object(aTHX_ meta, proto, args, TRUE); + ST(0) = proto; /* because object is mortal, we should return it as is */ + XSRETURN(1); } -OUTPUT: - RETVAL - void _initialize_object(SV* meta, SV* object, HV* args, bool is_cloning = FALSE) @@ -655,7 +656,7 @@ PPCODE: MODULE = Mouse PACKAGE = Mouse::Object -SV* +void new(SV* klass, ...) CODE: { @@ -663,6 +664,7 @@ CODE: AV* const xc = mouse_get_xc(aTHX_ meta); UV const flags = MOUSE_xc_flags(xc); SV* args; + SV* object; /* BUILDARGS */ if(flags & MOUSEf_XC_HAS_BUILDARGS){ @@ -692,12 +694,12 @@ CODE: } /* new_object */ - RETVAL = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc)); - mouse_class_initialize_object(aTHX_ meta, RETVAL, (HV*)SvRV(args), FALSE); - mouse_buildall(aTHX_ xc, RETVAL, args); /* BUILDALL */ + object = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc)); + mouse_class_initialize_object(aTHX_ meta, object, (HV*)SvRV(args), FALSE); + mouse_buildall(aTHX_ xc, object, args); /* BUILDALL */ + ST(0) = object; /* because object is mortal, we should return it as is */ + XSRETURN(1); } -OUTPUT: - RETVAL void DESTROY(SV* object) diff --git a/xs-src/MouseAccessor.xs b/xs-src/MouseAccessor.xs index 7fc55b6..1dad5e6 100644 --- a/xs-src/MouseAccessor.xs +++ b/xs-src/MouseAccessor.xs @@ -1,6 +1,7 @@ #include "mouse.h" #define CHECK_INSTANCE(instance) STMT_START{ \ + assert(instance); \ if(!(SvROK(instance) && SvTYPE(SvRV(instance)) == SVt_PVHV)){ \ croak("Invalid object instance: '%"SVf"'", instance); \ } \ @@ -331,24 +332,26 @@ XS(XS_Mouse_simple_predicate) SV* mouse_instance_create(pTHX_ HV* const stash) { + SV* instance; assert(stash); assert(SvTYPE(stash) == SVt_PVHV); - return sv_bless( newRV_noinc((SV*)newHV()), stash ); + instance = sv_bless( newRV_noinc((SV*)newHV()), stash ); + return sv_2mortal(instance); } SV* mouse_instance_clone(pTHX_ SV* const instance) { - HV* proto; - assert(instance); - + SV* proto; CHECK_INSTANCE(instance); - proto = newHVhv((HV*)SvRV(instance)); - return sv_bless( newRV_noinc((SV*)proto), SvSTASH(SvRV(instance)) ); + assert(SvOBJECT(SvRV(instance))); + + proto = newRV_noinc((SV*)newHVhv((HV*)SvRV(instance))); + sv_bless(proto, SvSTASH(SvRV(instance))); + return sv_2mortal(proto); } bool mouse_instance_has_slot(pTHX_ SV* const instance, SV* const slot) { - assert(instance); assert(slot); CHECK_INSTANCE(instance); return hv_exists_ent((HV*)SvRV(instance), slot, 0U); @@ -357,7 +360,6 @@ mouse_instance_has_slot(pTHX_ SV* const instance, SV* const slot) { SV* mouse_instance_get_slot(pTHX_ SV* const instance, SV* const slot) { HE* he; - assert(instance); assert(slot); CHECK_INSTANCE(instance); he = hv_fetch_ent((HV*)SvRV(instance), slot, FALSE, 0U); @@ -368,7 +370,6 @@ SV* mouse_instance_set_slot(pTHX_ SV* const instance, SV* const slot, SV* const value) { HE* he; SV* sv; - assert(instance); assert(slot); assert(value); CHECK_INSTANCE(instance); @@ -390,7 +391,6 @@ mouse_instance_delete_slot(pTHX_ SV* const instance, SV* const slot) { void mouse_instance_weaken_slot(pTHX_ SV* const instance, SV* const slot) { HE* he; - assert(instance); assert(slot); CHECK_INSTANCE(instance); he = hv_fetch_ent((HV*)SvRV(instance), slot, FALSE, 0U);