Возможно ли, что luabind проверяет, является ли вызов функции-члена экспортированного класса (объекта) допустимым объектом?
давайте предположим, что у меня есть класс с именем Actor, который использует luabind для lua. Я вызываю функцию lua из C ++ с объектом субъекта в качестве параметра. Теперь, прежде чем функция завершится, запись скрипта поместит объект актера в глобальную ссылку lua, к которой будет обращаться позже.
Позже объект субъекта удаляется с сайта C ++, вызывается другая функция, которая пытается получить доступ к недействительному объекту субъекта (любому методу из него) — и, очевидно, поскольку он был удален, это приводит к сбою (нарушение доступа)
образец:
local myObjRef = nil
function doSomethingWithActor(actor)
-- save, still valid object
actor:Say("hello")
myObjRef = actor
end
function calledAfterActorWasDeleted()
--- will crash if the c++ object has been deleted meanwhile, works fine if it still exists
myObjRef:Say("Crash...")
end
Проверка NIL здесь не помогает, это то, что можно проверить на сайте luabinds? Функции выполняются с использованием lua_pcall (….), а трассировка стека показывает ошибку при вызове luabinds call.hpp results = Maybe_yield (L, lua_gettop (L) — arguments, (Policies *) 0);
Если нет, есть ли другое решение, как убедиться, что кто-то, кто пишет скрипт, не может создать эти проблемы?
Теперь, прежде чем функция завершится, запись скрипта поместит объект актера в глобальную ссылку lua, к которой будет обращаться позже.
Вот тут-то и возникла ваша проблема. Если вы хотите, чтобы код Lua своя объект (то есть, сохранить существование этого объекта), то вам нужно использовать механику Luabind, чтобы сказать Luabind, что вы хотите сделать это. В противном случае, если вы передадите указатель на какую-либо функцию Lua, Luabind будет предполагать, что функция не будет пытаться завладеть ею.
Если вы хотите, чтобы право собственности было общий между Lua и Luabind, то вы должны обернуть свои объекты в boost::shared_ptr
и использовать для этого умные указатели Luabind.
Вы также можете лучше разделить свои сценарии. Если у вас есть какой-либо сценарий, который работает с конкретным актером, то этот сценарий и все содержащиеся в нем функции должны быть уничтожены (т.е. потерять все ссылки на него) вместе с объектом. Это требует правильной дисциплины кодирования на стороне C ++. Также потребуется, чтобы вы использовали среды Lua для правильной инкапсуляции каждого экземпляра скрипта, чтобы они не могли выкарабкаться через глобальные переменные. Наконец, вам нужно, чтобы C ++ поддерживал полный контроль над тем, когда скрипты вызываются, а когда нет.
Иначе владение — это то, о чем ваши сценаристы просто должны будут знать и быть осторожными. Они не могут обрабатывать параметры C ++ как любое старое значение Lua.
Если применение дисциплинированной практики программирования не представляется возможным или практичным для вас, то вам просто не придется передавать Lua фактический объект C ++. Вместо этого вам нужно передать Lua некоторый прокси-объект, который является ссылкой на оригинал. Хороший пример такого объекта — boost :: weak_ptr (хотя вы не передадите его точно Lua). Прокси будет переадресовывать вызовы на реальный объект. Если объект был удален, прокси обнаружит это и потерпит неудачу или ничего не сделает.
Я решил свою проблему следующим образом:
Когда я собираюсь удалить объект, я перебираю все функции lua из C ++ (у меня они есть в списке, они привязаны к определенным объектам-акторам каждый). Затем я проверяю каждое повышение (глобальные / локальные переменные, доступные для функции) — затем я сравниваю указатель пользовательских данных с моим объектом, который я собираюсь удалить — если они совпадают (и их классы), и NIL повышает значение. При желании я мог бы просто удалить эту оскорбительную функцию, потому что она все равно не будет работать хорошо.
Так что в следующий раз, когда функция вызывается, я просто получаю мягкую ошибку lua «пытаюсь получить доступ к xxx, nil value …» — больше никаких нарушений доступа.
Я знаю, что люди скажут: «Не используйте lua_getupvalue / lua_setupvalue — они только для отладки!» — но на самом деле нет никакого задокументированного или устного побочного эффекта — и в моем случае он совершенно безопасен и работает хорошо — также нет проблемы с оставшимися прокси-объектами, которые я не мог бы удалить.