调用处理程序数据的垃圾回收

我试图提供数据给函数调用处理程序,但我无法正确地收集垃圾。

如果我注释掉包含“ tpl->SetCallHandler(callFn, external); ”的行,则调用ObjWeakCallback 。 该函数从来没有被收集,但(至lessFnWeakCallback从来没有被调用,不pipe是什么)。

请注意,静态数据不是一个选项,因为这需要准备好每个进程的多个隔离。 isolate->setData也不是一个选项。 我完全错过了什么吗? 在v8::Function存储数据的正确方法是什么?


编辑:让我重新说明这个问题,以更好地描述我的意图…

我想创build一个函数模板(因为我需要使用它作为JS端的构造函数)。 我需要一些方法来发送一个void *给它的调用处理程序,但是这个数据必须是垃圾回收。

关于我到目前为止一直在尝试的一些笔记:

  • 使用Function::New(isolate, callHandler, External::New(isolate, data))工作,但不提供JS端构造函数的function(对于创build的对象不可能用SetInternalFieldCount)

  • FunctionTemplate::New(isolate, callHandler, External::New(isolate, data))提供了将数据传递给调用处理程序的能力,但是从不被垃圾回收(下面的工作示例)

  • 我尝试使用一个普通的函数,并返回一个新创build的Object ,但接下来的假设new Fn() instanceof Fn失败


 #include <v8.h> #include <iostream> // made static, just to simplify the example and prevent crashes // the persistents would normally be wrapped inside a "baton" together with required data v8::Persistent<v8::Value> p_obj; v8::Persistent<v8::Value> p_fn; void FnWeakCallback(const v8::WeakCallbackData<v8::Value, int>& data) { int* number = data.GetParameter(); std::cout << "GC fn " << number << '\n'; delete number; p_fn.Reset(); } void ObjWeakCallback(const v8::WeakCallbackData<v8::Value, int>& data) { int* number = data.GetParameter(); std::cout << "GC obj " << number << '\n'; delete number; p_obj.Reset(); } void callFn(const v8::FunctionCallbackInfo<v8::Value>& info) { std::cout << "called\n"; } void test(v8::Isolate* isolate) { v8::HandleScope scope(isolate); auto external = v8::External::New(isolate, new int{ 1 }); p_obj.Reset(isolate, external); p_obj.SetWeak(new int{ 1 }, ObjWeakCallback); auto tpl = v8::FunctionTemplate::New(isolate); tpl->SetCallHandler(callFn, external); // <====== tpl->InstanceTemplate()->SetInternalFieldCount(1); auto fn = tpl->GetFunction(); p_fn.Reset(isolate, fn); p_fn.SetWeak(new int{ 2 }, FnWeakCallback); } int main() { v8::V8::SetFlagsFromString("--expose-gc", 11); auto isolate = v8::Isolate::GetCurrent(); v8::HandleScope handle_scope(isolate); auto context = v8::Context::New(isolate); context->Enter(); test(isolate); isolate->RequestGarbageCollectionForTesting(v8::Isolate::kFullGarbageCollection); context->Exit(); return 0; } 

现在我已经欺骗了,看着代码

 void GCController::CollectAll(const gin::Arguments& args) { // In order to collect a DOM wrapper, two GC cycles are needed. // In the first GC cycle, a weak callback of the DOM wrapper is called back // and the weak callback disposes a persistent handle to the DOM wrapper. // In the second GC cycle, the DOM wrapper is reclaimed. // Given that two GC cycles are needed to collect one DOM wrapper, // more than two GC cycles are needed to collect all DOM wrappers // that are chained. Seven GC cycles look enough in most tests. 

所以答案一定是:第一次收集后你什么也看不到。