2013-06-20 1 views
1

У меня есть глобальный менеджер событий, позволяющий прослушивать с lambdas string именами событий.Вызов функции V8 вызывает нарушение доступа

// somewhere in the ModuleScript class 
Event->Listen("WindowResize", [=]{ 
    // ... 
}); 

Теперь, я хочу зарегистрироваться на мероприятиях с JavaScript. Поэтому я написал этот обратный вызов.

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(); 
} 

Когда событие инициировано, приложение выходит из строя с нарушением прав доступа. Мои мысли в том, что либо объект функции в данный момент недействителен, либо это проблема с областью JavaScript. Но я не мог понять.

Что вызывает нарушение доступа и как его преодолеть?

+0

Какое указание вызывает нарушение доступа? – Gonmator

+0

@Gonmator Ошибка находится в строке 'function-> Call (function, 0, NULL);'. – danijar

ответ

2

Я считаю, что здесь есть несколько потенциальных проблем.

Во-первых, вы не используете постоянный дескриптор для удержания функции JavaScript после завершения ModuleScript::jsOn(). К моменту запуска обработчика событий функция может исчезнуть. Рассмотрите возможность создания callback стойкой ручки.

Во-вторых, обработчик события должен ввести соответствующий контекст V8 перед вызовом функции JavaScript. В зависимости от вашей архитектуры может потребоваться явная блокировка и вход в изолятор V8.

В-третьих (и это может не быть проблемой в вашем конкретном сценарии), вам необходимо управлять временем жизни изоляции V8. Если ваш менеджер событий запускает события в фоновом потоке, вы должны убедиться, что обработчик событий каким-то образом препятствует тому, чтобы изолятор был удален из другого потока. К сожалению, это одна из областей, где API V8 не дает большой поддержки.

В-четвертых, чтобы предотвратить утечку, обработчик события должен утилизировать дескриптор постоянной функции после вызова функции.

Удачи вам!

+0

Я получил его работу с '[=]' capture clause и 'v8 :: HandleScope scope (v8 :: Isolate :: GetCurrent());' 'persistent-> Call (постоянный, 0, NULL);' в лямбда. – danijar

+0

Правильно, я забыл об объеме ручки. Рад, что ты заработал! – BitCortex