我将Spidermonkey嵌入我的C++应用程序中。我需要在本机C++中实现一些自定义jsval传递的自定义Javascript函数。我需要保护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中的任何先前的JSObject都可用于垃圾回收。

这些正确的方法可以创建可以跨函数调用传递的gc根临时变量吗?特别是,我的setter()替换先前的JSObject的方式是使现有JSObject可用于gc的正确方法(即无内存泄漏/崩溃)。

编辑:我认为垃圾收集是一个问题的原因是:

https://developer.mozilla.org/En/SpiderMonkey/JSAPI_User_Guide

在“JSAPI概念”下的“Javascript值”下:



https://developer.mozilla.org/en/SpiderMonkey_Garbage_Collection_Tips

示例3说“随您而行”,并显示如何将jsval分配给根。

最佳答案

无需为jsval之类的内容添加根。您只需要维护对脚本中值的引用。 SpiderMonkey GC基于引用计数,因此只要在当前作用域中引用它们,您的jsval不会消失:

var x = 5;

callNativeFun(x);

函数foo(){抛出true; }

print(nativeFunRef());

//脚本到此结束。 X和FOO以及调用NativeFun和nativeFunRef js函数签名的都将被垃圾回收。

在上面的代码示例中,x和foo都被全局对象保持引用。

只要脚本中定义了jsval指针内容,它就永远不会到达GC。确保您的二进制代码寿命结束后再也不会使用该值;也就是说,在脚本中使用完它后,对其调用delete或将其值设置为undefined由作用域终止的值或代理定义。如果预见到这些负面交互中的任何一种,则应在该jsval上设置GC根目录。

07-24 19:28