【发布时间】:2012-03-24 20:51:52
【问题描述】:
我将 Spidermonkey 嵌入到我的 C++ 应用程序中。我需要在本机 C++ 中实现一些自定义 Javascript 函数,这些函数传递一个 jsval。我需要保护 jsval 免受意外垃圾收集。我这样做是否合适:
(1) 在初始化例程中:
static jsval vp; // a STATIC variable, value unknown
JSBool init((JSContext *cx, uintN argc, jsval *vp) {
JS_AddValueRoot(cx, &vp);
}
(2)在一个实现Javascript函数setter()的c++函数中:
JSBool setter(JSContext *cx, uintN argc, jsval *vp) {
...
vp=...;// set to some JSObject and hopefully makes any previous JSObject available for gc
}
(3) 在实现 Javascript 函数 getter() 的同一编译单元内的第二个 C++ 函数调用中:
JSBool getter(JSContext *cx, uintN argc, jsval *vp) {
jsval somethingelse = vp; //directly retrieve the static value stored by setter()
....
}
我的 Javascript 脚本使用这样的函数调用:
init();
setter(...);
some_other_function_call_that_causes_gc();
getter();
setter(...);
some_other_function_call_that_causes_gc();
getter();
....
some_other_function_call_that_causes_gc();
setter(...);
some_other_function_call_that_causes_gc();
getter();
请注意,我从不调用 JS_RemoveRoot(),因为 static jsval vp 是我在 2 个函数调用之间传递的 jsval 的永久存储。而且,我不断在我的 setter() 中为 gc 根静态变量 vp 设置新值,假设存储在 jsval 中的任何先前的 JSObject 都可用于垃圾收集。
这些是创建可以跨函数调用传递的 gc 根临时变量的正确方法吗?特别是,我的 setter() 替换以前的 JSObject 的方式是使现有 JSObject 可用于 gc 的正确方法(即没有内存泄漏/崩溃)。
编辑:我认为垃圾收集是一个问题的原因是:
https://developer.mozilla.org/En/SpiderMonkey/JSAPI_User_Guide
在 JSAPI 概念、Javascript 值部分下:
jsval 本身并不能保护其所指对象免受垃圾的影响 收集器
https://developer.mozilla.org/en/SpiderMonkey_Garbage_Collection_Tips
示例 3 说“Root as you go”,并展示了如何将 jsval 分配给 root。
【问题讨论】:
-
我不明白为什么该变量会面临垃圾收集的风险?你能指出来吗?
-
因为在我的 Javascript 脚本中,我在 setter() 和 getter 之间调用了其他一些 Javascript 函数。请注意,setter() 设置它的值,稍后,另一个函数 getter() 获取该值。
-
函数有多少并不重要。如果没有对它的引用,那么某些东西只会是 GC。也许我不明白这个问题。您是否有证据表明 GC 正在删除您需要的变量?
-
我不确定。我对蜘蛛猴完全陌生。但是 JSAPI 用户指南说, jsval 不能保护其所指对象免受 gc 的影响。因此,即使我的 jsval 引用了一个 JSObject,该 JSObject 也可以被 gc'ed 并且我的 jsval 成为一个悬空指针。请参阅我的编辑。
标签: javascript garbage-collection spidermonkey