muppet wrote: >On Oct 1, 2004, at 4:50 AM, Steve Hay wrote: > > > >>Why does the following XS code leak? >> >> >... > > >>The Safefree(foo) is commented out in FooFree() because I believe that >>sv_usepvn() has reallo()'ed foo and will free() it for me when sv's >>refcount becomes 0. >> >> > >according to the docs for sv_usepvn(), that sounds right. however, >it's very mind-bending and obfuscated. you're transferring the >ownership of the memory to the SV, but still cleaning it up what it >points to yourself. i can't help but ask "why?" > I'm not cleaning up what it points to. As I said, the Safefree(foo) was deliberately commented-out. I'm cleaning up foo->buf because that was separately allocated and hasn't been "taken over" by the SV.
> > >by the way, if sv_usepvn() actually reallocates the pointer you passed >to it, then calling FooFree(foo) is going to be very, very bad. > Why? Calling Safefree(foo) is certainly very, very bad, which is why I wasn't doing it. Trying it to see if it made any difference was just an act of desperation. I'm quite relieved that it didn't fix anything. > >i added a couple of printfs to the code to see the actual pointer >addresses; > >void >foo() >PPCODE: >{ > SV *sv; > Foo *foo; > sv = NEWSV(0, 0); > foo = FooAlloc(aTHX); > printf (" -- foo %p\n", foo); > sv_usepvn(sv, (char *)foo, sizeof *foo); > printf (" pv %p\n", SvPV (sv, PL_na)); > SvPOK_only(sv); > SvREADONLY_on(sv); > FooFree(aTHX_ foo); > SvREFCNT_dec(sv); >} > >it looks like on my system the pointer is not getting realloc'd, and i >can't see a leak in the output of top (only a 4-byte increase in RSS >after 10000 reps). when i uncomment just the Safefree() in FooFree() >i get double-free warnings, so the SV is indeed freeing the memory >itself. > On my system (WinXP) the pointer is moved. MS docs for realloc() say that it might move the pointer, but it might not. Linking against the debug CRT apparently uses a different realloc() which guarantees to always move the pointer. Don't know if you have such an option on your system? Presumably you didn't see the leak because your memory wasn't moved. All this got me thinking some more, though, and I believe I've now answered my own question. FooFree(aTHX_ foo) is wrong because foo is still pointing to the space that was originally allocated. But the sv_usepvn() call has (in my case) moved the allocated memory block, so that original location is now toast. foo->buf (whatever that means now) is no longer necesarily pointing to where the 1024 char's were put [in fact, printing foo->buf before and after the sv_usepvn(), I see that it is not!], so Safefree(foo->buf) doesn't free those char's. What I need to do to fix it is retrieve the address of the (moved) Foo structure and FooFree() that. This doesn't leak: void foo() PPCODE: { SV *sv; Foo *foo; sv = NEWSV(0, 0); foo = FooAlloc(aTHX); sv_usepvn(sv, (char *)foo, sizeof *foo); SvPOK_only(sv); SvREADONLY_on(sv); FooFree(aTHX_ (Foo *)SvPVX(sv)); SvREFCNT_dec(sv); } - Steve ------------------------------------------------ Radan Computational Ltd. The information contained in this message and any files transmitted with it are confidential and intended for the addressee(s) only. If you have received this message in error or there are any problems, please notify the sender immediately. The unauthorized use, disclosure, copying or alteration of this message is strictly forbidden. Note that any views or opinions presented in this email are solely those of the author and do not necessarily represent those of Radan Computational Ltd. The recipient(s) of this message should check it and any attached files for viruses: Radan Computational will accept no liability for any damage caused by any virus transmitted by this email.