Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Re: Inline::C self-referential struct idioms and memory

by syphilis (Archbishop)
on Sep 08, 2015 at 02:38 UTC ( [id://1141297]=note: print w/replies, xml ) Need Help??


in reply to Inline::C self-referential struct idioms and memory

// should NOT alter refcount Node* set_parent(Node* self, Node* parent) { self->parent = parent; return self; }

There are memory management issues here. Why does this function return "self" ?
IOW, why is it not written as:
void set_parent(Node* self, Node* parent) { self->parent = parent; }
When it returns "self", it apparently decrements the reference count of "self". Here's a supporting demo:
#!perl -l use warnings; no warnings 'once'; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'EOC'; SV * foo(SV * in) { return in; } SV * get_ref(SV * in) { return newSVuv(SvREFCNT(in)); } EOC $x = 42; # $x refcnt == 1 %h = (fu => \$x); # $x refcnt == 2 print "x refcnt: ", get_ref($x); foo($x); # decrement $x refcnt print "x refcnt: ", get_ref($x); $y = foo($x); # decrement $x refcnt print "x refcnt: ", get_ref($x); print "y refcnt: ", get_ref($y); print "x: $x"; print "y: $y";
Which outputs:
x refcnt: 2 x refcnt: 1 x refcnt: 0 y refcnt: 1 Use of uninitialized value $x in concatenation (.) or string at try.pl + line 31. x: y: 42
I note that the return of set_parent() is not being captured, which reinforces my view that it could be rewritten as I've suggested.
But if it really does need to return "self" && the refcnt is not to be altered (as the comment specifies), then I think it's necessary to increment the refcnt of "self" before returning.

Either way worked fine for me.
However, for the same reason, I had to rewrite get_parent() as:
Node* get_parent(Node* self) { SvREFCNT_inc(self->parent); return self->parent; }
After that, it all seems to work fine for me (using your script and your typemap):
NODE: SV = IV(0x2c22740) at 0x2c22744 REFCNT = 1 FLAGS = (PADMY,ROK) RV = 0x45812c SV = PVMG(0x2a15cac) at 0x45812c REFCNT = 1 FLAGS = (OBJECT,IOK,READONLY,pIOK) IV = 40118476 NV = 0 PV = 0 STASH = 0x1d0edb4 "Node" --- PARENT: SV = IV(0x2c227f0) at 0x2c227f4 REFCNT = 1 FLAGS = (PADMY,ROK) RV = 0x45807c SV = PVMG(0x2a155ac) at 0x45807c REFCNT = 1 FLAGS = (OBJECT,IOK,READONLY,pIOK) IV = 40119340 NV = 0 PV = 0 STASH = 0x1d0edb4 "Node" --- FROM FIELD: SV = NULL(0x1d0e7) at 0x45817d REFCNT = -16777216 FLAGS = (TEMP,BREAK,OVERLOAD,EVALED,IsUV) --- destroying Node=SCALAR(0x45807c) at rut.pl line 58. destroying Node=SCALAR(0x45812c) at rut.pl line 58.
One other thing - I changed destroy_node() to:
void destroy_node(Node* self) { Safefree(self->parent); Safefree(self); }
That didn't blow anything up, from which I deduce that self->parent does need to be Safefree'd in order to avoid memory leaks.
OTOH, attempting to Safefree(self->sv) did crash the script - and I therefore deduce that doing so is not the right thing ;-)

Update: Whilst the above holds for my perls 5.10.0, 5.12.0, 5.14.0, 5.16.0, 5.18.0 and 5.20.0, on perl-5.22.0 the Safefree(self->parent) leads to a crash for me (on cleanup after the 2 calls to destroy_node have successfully completed) - so there's still a bit more to be unravelled.

Cheers,
Rob

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1141297]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (6)
As of 2024-03-28 16:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found