Как очистить или уничтожить QJSEngine?

Я собираю приложение, используя Qt 5.12, где пользователи будут загружать сценарии JS, которые взаимодействуют с приложением через его API. Эти сценарии объединены в «проекты» (т. е. несколько модулей JS, которые зависят друг от друга), и в любое время я хочу, чтобы в механизм JS загружался только один проект, поэтому, если пользователь загружает другой проект, я хочу, чтобы предыдущий контекст, который нужно очистить.

Основываясь на документации, я предположил, что если я просто удалю объект QJSEngine и создам новый, это позволит мне создать свежий JS-контекст.

QJSEngine* jsEngine = new QJSEngine();

// Load JS modules and run code...

jsEngine->collectGarbage();
delete jsEngine;

jsEngine = new QJSEngine();

// Load new JS modules...

Когда я пытаюсь запустить этот код, я получаю исключение нарушения прав доступа в delete jsEngine. Это действительно странно, потому что в самой документации указано

Мусор не собирается из постоянной кучи JS во время уничтожения QJSEngine. Если вам нужно освободить всю память, вызовите collectGarbage вручную прямо перед уничтожением QJSEngine.

что для меня означало, что я должен быть в состоянии сделать это. У кого-нибудь есть идеи? Заранее спасибо!


person yah_nosh    schedule 11.04.2019    source источник
comment
Я даже пытался использовать deleteLater или сделать главное окно родителем каждого QJSEngine, который я создаю (и, таким образом, очищать их, когда приложение закрывается), но проблемы сохраняются. По какой-то причине в тот момент, когда у меня есть более одного экземпляра, или если я пытаюсь удалить экземпляр в любое другое время, кроме как при закрытии приложения, я получаю какую-то ошибку доступа к памяти.   -  person yah_nosh    schedule 13.04.2019


Ответы (2)


Итак, получается, что я дурак и забыл включить одну важную деталь: мое приложение также предоставляет объект «Интерфейс JavaScript» движку JS, используя QJSEngine::newQObject, поэтому я просто воссоздал эта проблема.

Решение точно такое же: использование QQmlEngine::setObjectOwnership устраняет проблему.

person yah_nosh    schedule 25.04.2019

Убедитесь, что у вас нет оставшихся QJSValues.

В качестве альтернативы, если вы просто хотите очистить состояние. Очистите QJSEngine::globalObject() или просто избегайте использования корневого JS-состояния, чтобы между проектами ничего не утекало.

person Allan Jensen    schedule 24.04.2019
comment
Хорошо, я только что узнал, в чем был источник моей проблемы: я выставляю свой класс интерфейса, используя newQObject, для глобального объекта JS (у меня есть объект, который дает указатель на себя при вызове функции), и это вызывает сбой, когда я пытаюсь удаление QJSEngine. Но теперь я очищаю его перед удалением? Я попытался использовать deleteProperty для глобального объекта, но это не сработало. - person yah_nosh; 26.04.2019
comment
Хороший вопрос. Я бы предположил, что вам нужно как-то перестать ссылаться на него, а затем активировать сборку мусора. Обратите внимание, что существуют также разные модели владения для мостовых объектов (контролируемых либо C++, либо JS, если я правильно помню) - person Allan Jensen; 26.04.2019
comment
Смотрите ответ выше. Оказывается, есть прямое решение, но добраться до него довольно неинтуитивно. Спасибо за ваши комментарии, они помогли мне найти правильный ответ. - person yah_nosh; 27.04.2019