调用V8函数会导致访问冲突 [英] Calling V8 function causes access violation
问题描述
我有一个全局事件管理器,允许您使用lambda表达式来监听 string
事件名称。
//在ModuleScript类的某处
Event-> Listen(WindowResize,[=] {
// ...
});
现在,我也想注册JavaScript事件。因此,我编写了这个回调函数。
v8 :: Handle< v8 :: Value> ModuleScript :: jsOn(const v8 :: Arguments& args)
{
//获取指向类的指针,因为我们处于静态方法
ModuleScript * module =(ModuleScript *)HelperScript: :展开(args.Data());
//获取我们想要从参数中注册的事件名称
if(args.Length()< 1 ||!args [0] - > IsString())
return v8 :: Undefined();
string name = * v8 :: String :: Utf8Value(args [0]);
//从参数获得回调函数
if(args.Length()< 2 ||!args [1] - > IsFunction())
return v8: :未定义();
v8 :: Handle< v8 :: Function> callback =
v8 :: Local< v8 :: Function> :: Cast(args [1] - > ToObject());
//在全局事件管理器中注册事件
module->事件 - >监听(名称,[=] {
//创建持久句柄,以使函数保持有效
//也许这不起作用,我不知道
v8 :: Persistent< v8 :: Function> function =
v8 :: Persistent< v8 :: Function> :: New(args.GetIsolate(),callback);
//执行回调函数
//导致访问冲突
函数 - >调用(函数,0,NULL);
});
return v8 :: Undefined();
}
当事件被触发时,应用程序会因访问冲突而崩溃。我的想法是,这个函数对象现在不再有效,或者它是一个JavaScript范围问题。但我无法弄清楚。
什么原因导致访问违规以及如何克服它?
我相信这里有几个潜在的问题。
首先,您没有使用持久化句柄来保存 ModuleScript :: jsOn()
终止。当你的事件处理程序被调用时,函数可能会消失。考虑让回调
一个持久句柄。
祝你好运!
I have a global event manager, allowing you to listen with lambdas to string
event names.
// somewhere in the ModuleScript class
Event->Listen("WindowResize", [=]{
// ...
});
Now, I want to register to events from JavaScript, too. Therefore, I wrote this callback.
v8::Handle<v8::Value> ModuleScript::jsOn(const v8::Arguments& args)
{
// get pointer to class since we're in a static method
ModuleScript *module = (ModuleScript*)HelperScript::Unwrap(args.Data());
// get event name we want to register to from arguments
if(args.Length() < 1 || !args[0]->IsString())
return v8::Undefined();
string name = *v8::String::Utf8Value(args[0]);
// get callback function from arguments
if(args.Length() < 2 || !args[1]->IsFunction())
return v8::Undefined();
v8::Handle<v8::Function> callback =
v8::Local<v8::Function>::Cast(args[1]->ToObject());
// register event on global event manager
module->Event->Listen(name, [=]{
// create persistent handle so that function stays valid
// maybe this doesn't work, I don't know
v8::Persistent<v8::Function> function =
v8::Persistent<v8::Function>::New(args.GetIsolate(), callback);
// execute callback function
// causes the access violation
function->Call(function, 0, NULL);
});
return v8::Undefined();
}
When the event is triggered, the application crashes with a access violation. My thoughts are that either the function object isn't valid at this time anymore, or it is a JavaScript scope issue. But I couldn't figure it out.
What causes the access violation and how to overcome it?
I believe there are several potential issues here.
First, you're not using a persistent handle to hold the JavaScript function after ModuleScript::jsOn()
terminates. By the time your event handler is invoked, the function might be gone. Consider making callback
a persistent handle.
Second, your event handler needs to enter an appropriate V8 context before calling the JavaScript function. Depending on your architecture, explicitly locking and entering the V8 isolate may be required as well.
Third (and this may not be an issue in your specific scenario), you need to manage the lifetime of the V8 isolate. If your event manager fires events on background threads, you have to make sure your event handler somehow prevents the isolate from being disposed from another thread. Unfortunately this is one area where the V8 API doesn't provide much help.
Fourth, to prevent a leak, your event handler should dispose the persistent function handle after invoking the function.
Good luck!
这篇关于调用V8函数会导致访问冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!