The bug reports on CPAN for List::Util don't list it, but I looked at the source code, and found the following C code for reduce:
void
reduce(block,...)
SV * block
PROTOTYPE: &@
CODE:
{
SV *ret = sv_newmortal();
int index;
GV *agv,*bgv,*gv;
HV *stash;
CV *cv;
OP *reducecop;
PERL_CONTEXT *cx;
SV** newsp;
I32 gimme = G_SCALAR;
U8 hasargs = 0;
bool oldcatch = CATCH_GET;
if(items <= 1) {
XSRETURN_UNDEF;
}
agv = gv_fetchpv("a", TRUE, SVt_PV);
bgv = gv_fetchpv("b", TRUE, SVt_PV);
SAVESPTR(GvSV(agv));
SAVESPTR(GvSV(bgv));
GvSV(agv) = ret;
cv = sv_2cv(block, &stash, &gv, 0);
reducecop = CvSTART(cv);
SAVESPTR(CvROOT(cv)->op_ppaddr);
CvROOT(cv)->op_ppaddr = PL_ppaddr[OP_NULL];
#ifdef PAD_SET_CUR
PAD_SET_CUR(CvPADLIST(cv),1);
#else
SAVESPTR(PL_curpad);
PL_curpad = AvARRAY((AV*)AvARRAY(CvPADLIST(cv))[1]);
#endif
SAVETMPS;
SAVESPTR(PL_op);
SvSetSV(ret, ST(1));
CATCH_SET(TRUE);
PUSHBLOCK(cx, CXt_SUB, SP);
PUSHSUB(cx);
if (!CvDEPTH(cv))
(void)SvREFCNT_inc(cv);
for(index = 2 ; index < items ; index++) {
GvSV(bgv) = ST(index);
PL_op = reducecop;
CALLRUNOPS(aTHX);
SvSetSV(ret, *PL_stack_sp);
}
ST(0) = ret;
POPBLOCK(cx,PL_curpm);
CATCH_SET(oldcatch);
XSRETURN(1);
}
Now the problem is that I may know how to read C, but I sure don't know XS. My wild guess is that the
if (!CvDEPTH(cv))
(void)SvREFCNT_inc(cv);
should be matched with a decrement (most likely SvREFCNT_dec) to prevent memory leaking. But quite possibly, the problem might lie elsewhere in the XS code. I think that you best report the bug to the author via RT, and include your test snippet or a link to this thread. |