However, Adrien Enache noticed that I was leaking memory all over the place:
http://rt.perl.org/rt3/Ticket/Display.html?id=24624
I fixed everything I could find and released a new package to CPAN:
http://search.cpan.org/~jpeacock/version-0.34/
but I find that I am still leaking memory in the replacement UNIVERSAL::VERSION code, and I am stymied as to where.
If I comment out the two instances of upg_version() in the replacement U::V XS code, as well as the call to vcmp(), I see no leakage. However, just uncommenting a single call to upg_version() leaks immediately. I have been unable to see any leakage when just directly calling version->new() which in essence calls exactly the same code.
upg_version() creates a temporary string copy (Safefree()'d) of the incoming SV and then calls scan_version(), which in turn does this (where rv is the incoming SV which will ultimately be returned to the top level caller):
SV* sv = newSVrv(rv, "version"); /* create an SV and upgrade the RV */ (void)sv_upgrade(sv, SVt_PVAV); /* needs to be an AV type */
...no allocation of memory here...
/* Append revision */ av_push((AV *)sv, newSViv(rev));
After this code has run, the rv contains a reference to an AV, containing 2 or more IV elements. Everything has only 1 reference up the line.
The top level code (in UNIVERSAL_VERSION) has done this:
SV *nsv = sv_newmortal(); sv_setsv(nsv, sv); sv = nsv; if ( !sv_derived_from(sv, "version")) upg_version(sv);
and sv has, in fact, been mortalized (I've checked using sv_dump).
If the refcount on the mortalized sv (which now contains a reference to the AV) is 1, the AV also has a refcount of 1, and the refcount of each element of the AV is 1, then the next FREETMPS should delete everything, right?
This doesn't leak:
perl -Mversion -e 'eval "$v = version->new(1.0)" while 1'
but this does:
perl -Mversion -e 'eval "use module 1.0" while 1'
for even the most trivial module.
TIA
John
p.s. rather than attaching the source code here; the current version module can be retrieved from CPAN