On Sun, Nov 28, 2004 at 02:24:28PM +0100 Tels wrote:

> I have seen some alarming memory growth on an application of mine, and have 
> the hunch that Math::BigInt::GMP is leaking memory. The included test script 
> outputs:

[...]

> void
> _sub(Class,x,y, ...)
>         SV*     x
>         SV*     y
>   PREINIT:
>         mpz_t* TEMP;
>         mpz_t* TEMP_1;
>         mpz_t* TEMP_2;
>   PPCODE:
>     GMP_GET_ARGS_0_1;   /* (TEMP, TEMP_1) = (x,y)  */
>     if ( items == 4 && SvTRUE(ST(3)) )
>       {
>       /* return new(y - x) */
>       /* need to create TEMP_2 or it will ssegfault */
>       TEMP_2 = malloc (sizeof(mpz_t)); mpz_init(*TEMP_2);
> 
>       mpz_sub(*TEMP_2, *TEMP, *TEMP_1);
> 
>       PUSHs(sv_setref_pv(sv_newmortal(), "Math::BigInt::GMP", (void*)TEMP_2));
>       /*PUSHs(sv_setref_pv(y, "Math::BigInt::GMP", (void*)TEMP_2)); */

The problem is this line (any of the two). sv_setref_pv() returns a new
SV which you need to mortalize:

    PUSHs(sv_2mortal(sv_setref_pv(y, "Math::BigInt::GMP", (void*)TEMP_2));

I find this fact slightly unintuitiv as I wouldn't expect a sv_set*
function to create a new SV. However, the source clearly says:
    
    SV*
    Perl_sv_setref_pv(pTHX_ SV *rv, const char *classname, void *pv)
    {
        ...
        sv_setiv(newSVrv(rv,classname), PTR2IV(pv));
        return rv;
    }

This is actually a good reason to use a typemap on return values and
assign TEMP2 to RETVAL. The C-code generated by xsubpp mortalizes the
wrapper SV for RETVAL. Maybe this is one reason why I wasn't really
aware that sv_setref_pv needs mortalizing since I always use it through
a typemap.

Other than that, you shouldn't be using malloc or any of the other
memory allocators of the libc directly. The perlapi defines wrappers
for them: New/Newz/Renew and Safefree for freeing thusly allocated memory. 
See perlclib.pod for details.

Tassilo
-- 
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval

Reply via email to