我将 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(),因为静态 jsval vp是在 2 个函数调用之间传递的我的 jsval 的永久存储。而且,我不断在我的 setter() 中为 gc 根静态变量 vp 设置新值,假设存储在 jsval 中的任何 previouis 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 说“随你去的根”,并展示了如何将 jsval 分配给根。