24

V8 的文档解释了如何创建包装 C++ 对象的 Javascript 对象。Javascript 对象持有指向 C++ 对象实例的指针。我的问题是,假设您在堆上创建了 C++ 对象,当 Javascript 对象被 gc 收集时,如何获得通知,以便释放堆分配的 C++ 对象?

4

3 回答 3

23

诀窍是创建一个Persistent句柄(链接到 API 参考中的第二个要点:“Persistent句柄不保存在堆栈上,只有在您专门删除它们时才会被删除。......当您需要保留一个对多个函数调用的对象的引用,或者当句柄生命周期不对应于 C++ 范围时。”),并调用MakeWeak()它,传递一个回调函数,该函数将进行必要的清理(“可以使持久句柄变弱,当对对象的唯一引用来自弱持久句柄时,使用Persistent::MakeWeak, 触发垃圾收集器的回调。” - 也就是说,当所有“常规”句柄都超出范围并且垃圾收集器即将删除目的)。

Persistent::MakeWeak方法签名是:

void MakeWeak(void* parameters, WeakReferenceCallback callback);

whereWeakReferenceCallback被定义为一个指向函数的指针,带有两个参数:

typedef void (*WeakReferenceCallback)(Persistent<Object> object,
                                      void* parameter);

这些可以在与 V8 作为公共 API 一起分发的 v8.h 头文件中找到。

您希望传递给的函数MakeWeak清理Persistent<Object>对象参数,该参数将在作为回调调用时传递给它。该void* parameter参数可以被忽略(或者void* parameter可以指向包含需要清理的对象的 C++ 结构):

void CleanupV8Point(Persistent<Object> object, void*)
{
    // do whatever cleanup on object that you're looking for
    object.destroyCppObjects();
}

Parameter<ObjectTemplate> my_obj(ObjectTemplate::New());

// when the Javascript part of my_obj is about to be collected
// we'll have V8 call CleanupV8Point(my_obj)
my_obj.MakeWeak(NULL, &CleanupV8Point);
于 2008-10-06T22:00:05.680 回答
0

一般来说,如果垃圾收集语言可以保存对语言引擎之外的资源(文件、套接字或在您的情况下为 C++ 对象)的引用,您应该提供一个“关闭”方法来尽快释放该资源,没有必要等到GC 认为销毁你的对象是值得的。

如果您的 C++ 对象需要大量内存并且垃圾收集的对象只是一个引用,情况会变得更糟:您可能会分配数千个对象,而 GC 只看到几 KB 的小对象,不足以触发收集;而 C++ 方面正在与数十兆字节的陈旧对象作斗争。

于 2008-10-06T18:12:48.743 回答
0

在某个封闭范围内(对象或函数)完成所有工作。然后,您可以在超出范围时安全地删除 C++ 对象。GC 不检查指针是否存在指向对象。

于 2008-10-06T20:38:24.363 回答