如何释放包裹的 C++ 当关联的 Javascript 对象在 V8 中被垃圾收集时,对象?

发布于 2024-07-06 22:19:36 字数 232 浏览 7 评论 0原文

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

V8's documentation explains how to create a Javascript object that wraps a C++ object. The Javascript object holds on to a pointer to a C++ object instance. My question is, let's say you create the C++ object on the heap, how can you get a notification when the Javascript object is collected by the gc, so you can free the heap allocated C++ object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

缱倦旧时光 2024-07-13 22:19:36

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

Persistent::MakeWeak 方法签名为:

void MakeWeak(void* parameters, WeakReferenceCallback callback);

其中 WeakReferenceCallback 被定义为带有两个参数的函数指针:

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

这些参数可在随以下版本分发的 v8.h 头文件中找到: V8 作为公共 API。

您可能希望传递给 MakeWeak 的函数来清理 Persistent对象参数,该参数将在作为回调调用时传递给它。 可以忽略 void* 参数 参数(或者 void* 参数 可以指向保存需要清理的对象的 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);

The trick is to create a Persistent handle (second bullet point from the linked-to API reference: "Persistent handles are not held on a stack and are deleted only when you specifically remove them. ... Use a persistent handle when you need to keep a reference to an object for more than one function call, or when handle lifetimes do not correspond to C++ scopes."), and call MakeWeak() on it, passing a callback function that will do the necessary cleanup ("A persistent handle can be made weak, using Persistent::MakeWeak, to trigger a callback from the garbage collector when the only references to an object are from weak persistent handles." -- that is, when all "regular" handles have gone out of scope and when the garbage collector is about to delete the object).

The Persistent::MakeWeak method signature is:

void MakeWeak(void* parameters, WeakReferenceCallback callback);

Where WeakReferenceCallback is defined as a pointer-to-function taking two parameters:

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

These are found in the v8.h header file distributed with V8 as the public API.

You would want the function you pass to MakeWeak to clean up the Persistent<Object> object parameter that will get passed to it when it's called as a callback. The void* parameter parameter can be ignored (or the void* parameter can point to a C++ structure that holds the objects that need cleaning up):

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);
季末如歌 2024-07-13 22:19:36

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

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

In general, if a garbage-collected language can hold references to resources outside of the language engine (files, sockets, or in your case C++ objects), you should provide a 'close' method to release that resource ASAP, no point waiting until the GC thinks it's worthwhile to destroy your object.

it gets worse if your C++ object is memory-hungry and the garbage-collected object is just a reference: you might allocate thousands of objects, and the GC only sees a few KB's of tiny objects, not enough to trigger collection; while the C++ side is struggling with tens of megabytes of stale objects.

挽心 2024-07-13 22:19:36

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

Do all your work in some closed scope (of object or function).
Then you can safely remove the C++ object when you went out of scope. GC doesn't check pointers for existence of pointed objects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文