c++ - 调用处理程序数据的垃圾收集

标签 c++ node.js garbage-collection v8 embedded-v8

我正在尝试向函数调用处理程序提供数据,但我无法正确地对其进行垃圾回收。

如果我注释掉包含“tpl->SetCallHandler(callFn, external);”的行,将调用 ObjWeakCallback。不过,该函数永远不会被收集(至少永远不会调用 FnWeakCallback,无论如何)。

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


编辑:让我重新表述问题以更好地描述我的意图......

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

到目前为止我一直在尝试的一些注意事项:

  • 使用 Function::New(isolate, callHandler, External::New(isolate, data)) 有效,但不提供 JS 端构造函数(无法为 SetInternalFieldCount创建的对象)

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

  • 我尝试使用普通函数并返回一个新创建的 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;
}

最佳答案

现在我作弊看了code

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.

所以答案一定是:第一次收集后你将看不到任何东西。

关于c++ - 调用处理程序数据的垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25879615/

相关文章:

c# - 如何轻松地为一段 C# 代码计时?

c++ - 未定义对 C++ 中析构函数错误的引用?

c++ - 无法在 64 位 Debian 上运行 32 位二进制文​​件

javascript - 更改模块路径

node.js - 记录使用 gulp-connect 完成的所有请求

c++ - 从 OpenGL 应用程序中提取颜色/深度缓冲区

javascript - 如何在 promise 之间等待

c# - .NET 垃圾收集器能否收集作为类成员的对象?

android - 我如何停止android垃圾收集器?可能吗?

java - Jmeter req/s 速率下降,加载 org.mozilla.javascript.gen._cmd__