Leaking data in SetAccessor

59 views
Skip to first unread message

Gerhans

unread,
Apr 13, 2012, 5:57:45 PM4/13/12
to v8-users
Hi - I'm having some trouble preventing a leak of the data parameter
passed to ObjectTemplate::SetAccessor(). I'm attempting to use a
Persistent handle to an externally new'd pointer as the 'data'
parameter, but the dataDeleterFn I pass to MakeWeak() never seems to
fire. More specifically, I'm attempting to replace the Accessor on the
fly, which of course is the only reason I would expect the data to be
cleaned up. I've tried to force this by calling my setAccessor()
function repeatedly (100,000+ times) and am successfully forcing V8 to
garbage collect overall, but watching my app in Instruments it's clear
that it's leaking memory. Does anyone have any insight into this?

void setAccessor( const std::string &propName, void *data )
{
v8::HandleScope handleScope;
v8::Local<External> dataExternal = v8::External::New( data );
v8::Persistent<External> dataPersistent =
Persistent<External>::New( dataExternal );
dataPersistent.MakeWeak( accessor, dataDeleterFn ); // <--- never
fires
mInstanceTemplate->SetAccessor( v8::String::New( propName.c_str() ),
getterFn, setterFn, dataPersistent );
}

Thanks in advance...

Stephan Beal

unread,
Apr 13, 2012, 6:00:58 PM4/13/12
to v8-u...@googlegroups.com
On Fri, Apr 13, 2012 at 11:57 PM, Gerhans <ger...@gmail.com> wrote:
fire. More specifically, I'm attempting to replace the Accessor on the
fly, which of course is the only reason I would expect the data to be
cleaned up.

As a partial workaround, you could clean up the previous dataPersistent on each call with a few minor changes. That would leak the last one set, but not any which have been overwritten.


--
----- stephan beal
http://wanderinghorse.net/home/stephan/

Gerhans

unread,
Apr 13, 2012, 9:59:10 PM4/13/12
to v8-u...@googlegroups.com
Thanks for the reply Stephan. You're imagining a map<string,void*> kind of thing? Seems workable, and I may have to resort to that, but I was hoping to understand the nature of the problem better. Is this my bug or V8's? I'm new to V8 so it seems likely I'm doing something wrong.

Thanks again...

On Friday, April 13, 2012 6:00:58 PM UTC-4, Stephan Beal wrote:

Charles A. Lopez

unread,
Apr 14, 2012, 1:35:06 AM4/14/12
to v8-u...@googlegroups.com
The code is very ugly/messy.

Do you have a base class? What kind of object is your data? 

What kind of data structure or abstract data type is this? 

There's a function/method called MakeWeak, so there's some kind of strength value involved? 

You have a leak? The problem might be bigger than that. Simplify. Make your code clearer to understand. 



Stephan Beal

unread,
Apr 14, 2012, 4:36:27 AM4/14/12
to v8-u...@googlegroups.com
On Sat, Apr 14, 2012 at 3:59 AM, Gerhans <ger...@gmail.com> wrote:
Thanks for the reply Stephan. You're imagining a map<string,void*> kind of thing?

Ah, i didn't consider that each _instance_ of course has its own value. i was thinking about saving the last one in a static.
 
Seems workable, and I may have to resort to that, but I was hoping to understand the nature of the problem better. Is this my bug or V8's? I'm new to V8 so it seems likely I'm doing something wrong.


i don't see anything wrong with what you've done :(.

Gerhans

unread,
Apr 14, 2012, 8:52:47 AM4/14/12
to v8-u...@googlegroups.com
@Stephan - thanks for at least confirming I'm not doing anything obviously wrong.

@Charles - I'm sorry the code looks messy to you. I wasn't anticipating the Google Groups web interface introducing a hard-wrap into my post. If you have suggestions for improvement beyond the resulting illegible formatting I'd appreciate them.

That said, I'm not sure how the nature of the void *data affects the question. If it's relevant for some reason I don't understand, it represent a small class encoding a pointer to member variable. The problem is that my "dataDeleterFn" never fires (which I have double-confirmed through breakpoints). I have already confirmed this is the source of my leak using Instruments on Mac OS X, and I've forced V8 to garbage collect so it's not a matter of waiting out GC.

Thanks again...

Stewart Mckinney

unread,
Apr 16, 2012, 12:30:09 PM4/16/12
to v8-u...@googlegroups.com
Gerhans:

It seems like you are leaking memory from the void* not getting cleaned up, and that the void* is being passed to the SetAccessor function for some generic getter/setter purpose?

If its the case that the callback is not firing, perhaps its true that the V8 Garbage Collector is not firing the MakeWeak function because there is no reference in your Javascript Context to said External handle? (i.e, you are using the External handle as a data parameter to the SetAccessor function, but since it isn't an internal field of an object that is within the Javascript context, the GC doesn't know about it and thus never sees it on its collection passes and never fires the Weak callback on it because its not on its list?)

Anyone know if thats typical V8 GC behavior?

(Maybe the fix here is to put the MakeWeak callback on the FunctionTemplate itself? That way, if the constructor function ever dissapears from the context and there are no child objects left in the context, the MakeWeak callback will fire and appropriately get rid of the void* data you pass.)


--
Reply all
Reply to author
Forward
0 new messages