The main problem is that you aren't (in your original version; didn't look at your update) freeing the temporary arrays. It is not enough to just av_undef() them, you also have to dec the AV reference counts.

Also, when you copy the original array, you are copying the SVs into the temp array, but not duping the SVs themselves, thus when you av_undef() the temp arrays, you are discarding the SVs that still have pointers in the original array. This may do more duplication than is strictly necessary; but as is it runs clean:

#! perl -slw use strict; use Inline C => <<'END_OF_PERCENT2_C_CODE'; #define SvSIOK(sv) ((SvFLAGS(sv) & (SVf_IOK|SVf_IVisUV)) == SVf_IOK) #define SvNSIV(sv) (SvNOK(sv) ? SvNVX(sv) : (SvSIOK(sv) ? SvIVX(sv) : +sv_2nv(sv))) static I32 S_sv_ncmp(pTHX_ SV *a, SV *b) { const NV nv1 = SvNSIV(a); const NV nv2 = SvNSIV(b); return nv1 < nv2 ? -1 : nv1 > nv2 ? 1 : 0; } void percent2(SV* sv, ...) { Inline_Stack_Vars; I32 i; I32 arrayLen; I32 remove_count; AV* data; AV* data_tmp; double value; int index; SV** pvalue; double retval; AV* ret; ret = newAV(); data_tmp = newAV(); data = (AV*)SvRV(Inline_Stack_Item(0)); if( SvTYPE(data) != SVt_PVAV ) { return; } /* determine the length of the array */ arrayLen = av_len(data) + 1; if (arrayLen > 0) { /* use new tmp array to prevent reordering caller array*/ for (i = 0; i < arrayLen; i++) { pvalue = av_fetch(data,i,0); av_push( data_tmp, newSVsv( *pvalue ) ); // Copy the SVs + so that you don't destroy the original array when freeing the temp } /* sort array in ascending order */ sortsv(AvARRAY(data_tmp),arrayLen, S_sv_ncmp); /* loop through data array and delete undef entries */ remove_count = 0; for (i = 0; i < arrayLen; i++) { /* Fetch the scalar located at i from the array.*/ pvalue = av_fetch(data_tmp,i,0); if (!SvOK(*pvalue)) { remove_count++; } else { break; } } for (i = 0; i < remove_count; i++) { av_shift(data_tmp); } arrayLen -= remove_count; } if (arrayLen > 0) { /* loop through percent args and find given value in array */ for (i = 1; i < Inline_Stack_Items; i++) { value = SvNV(Inline_Stack_Item(i)); if (value <= 100 && value >= 0){ if (value == 100){ value -= 1e-13; } index = (int)((arrayLen-1) * value/100); /* fetch scalar located at calculated index*/ pvalue = av_fetch(data_tmp,index,0); av_push( ret, newSVsv( *pvalue ) ); /// ditto } } } /* push into return stack */ Inline_Stack_Reset; arrayLen = av_len(ret) + 1; if (arrayLen > 0) { for (i = 0; i < arrayLen; i++) { /* fetch the scalar located at i from the array.*/ pvalue = av_fetch(ret,i,0); /* dereference the scalar into a numeric value. */ retval = SvNV(*pvalue); Inline_Stack_Push( sv_2mortal( newSVnv( retval ) ) ); // M +ortalise the return values } } else { Inline_Stack_Push( sv_2mortal( newSVnv(0) ) ); // Mortalise +the return values } Inline_Stack_Done; av_undef( ret ); // free array memory SvREFCNT_dec( ret ); // free the AV itself av_undef( data_tmp ); // ditto SvREFCNT_dec( data_tmp ); } END_OF_PERCENT2_C_CODE my @data = map int( rand 100 ), 1 .. 100;; print join '|', percent2( \@data, 1, 50 ) for 1 .. 1e9;;

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

In reply to Re: Inline C memory leak by BrowserUk
in thread Inline C memory leak by skateamac

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.