A hard to pin down memory leak involving sysmem_newptr

Aug 1, 2010 at 3:54pm

A hard to pin down memory leak involving sysmem_newptr

Hi,

There’s very obviously a leak happening with one of my externals, cv.jit.shift, when it’s used in a particular fashion. There is no problem if you just send matrices at regular intervals. However, in the abstraction cv.jit.touches, I need, for every frame, to send the same matrix repeatedly (a few hundred times). That’s when problems start happening.

The culprit seems to be sysmem_newptr, which surprised me because I don’t use directly. I was able to further narrow the problem to my bang method, which surprised me even more, because I’m not doing all that much in there.

It’s probably easier to understand what’s happening by having a look at this screen grab:

http://jmpelletier.com/video/sysmem_newptr-leak.mov

That the memory seems to get released at least some time when I’m just sending individual bangs would seem to indicate a possible scheduling/garbage collection issue, but as far as I can tell whatever’s happening is in the Max API, rather than my own program.

Here’s the full source of my bang method:

//Inside main()
ps_getbox = gensym(“getbox”);
ps_getrot = gensym(“getvertices”);
ps_getmass = gensym(“getmass”);

/*(..)*/

void max_cv_jit_shift_bang(t_max_cv_jit_shift *x)
{
long ac = 0;
t_atom *av = NULL;
void *o;

if (max_jit_mop_getoutputmode(x))
{
o=max_jit_obex_jitob_get(x);

//Output mass
jit_object_method(o,ps_getmass,&ac,&av);
//just in case…
if (ac!=1)
error(“Could not get mass from Jitter object.”);
else
{
outlet_float(x->massout,jit_atom_getfloat(av));
}

//Output rotated frame
ac = 0;
av = NULL;
jit_object_method(o,ps_getrot,&ac,&av);
//just in case…
if (ac!=8)
error(“Could not get rotated frame from Jitter object.”);
else
{
outlet_anything(x->boxout2,_jit_sym_list,ac,av);
}

//Output bounding box
ac = 0;
av = NULL;
jit_object_method(o,ps_getbox,&ac,&av);
//just in case…
if (ac!=4)
error(“Could not get bounding rectangle from Jitter object.”);
else
{
outlet_anything(x->boxout,_jit_sym_list,ac,av);
}
}
}

Here’s the patch I use for testing:

– Pasted Max Patch, click to expand. –
#51595
Aug 1, 2010 at 11:03pm

There might be other issuses, but minimally, it looks like you need to free the memory allocated in your get* calls. Keep in mind that attribute accessors allocate memory for av, if memory is not passed in (in which case ac would be the max atom count of the memory av points to).

i.e. before setting av to null, each time:

if (av)
sysmem_freeptr(av);

And again, finally at the end, after outputting your atoms from your getbox call.

#185089
Aug 2, 2010 at 1:42am

Hi Joshua, thanks for the quick reply.

That was it. I guess it wasn’t hard to pin down at all. Too much PHP lately has made my mind soft. I don’t even remember why I was setting that pointer back to NULL…

Thanks again, you saved a few precious hairs from an untimely demise.

Jean-Marc

#185090
Aug 2, 2010 at 4:31am

Glad to hear. Be sure to still zero ac and av before calling subsequent getters, so they know to allocate new pointers rather than the ones just freed.

#185091
Aug 2, 2010 at 7:42am

Yes, but since the number of arguments is constant, it’s probably just better to allocate once at init time and release in free. That way, malloc won’t get called a few hundred times per frame…

#185092

You must be logged in to reply to this topic.