Как отследить утечки памяти / отказались от Lua? - PullRequest
3 голосов
/ 01 февраля 2012

Я использую cocos2d-x с Lua для разработки.Недавно я использовал Instruments и обнаружил некоторый объем памяти, который заброшен: cocos2d-x выполняет освобождение объектов в своем собственном пуле авто-выпусков, но у меня все еще есть ссылка, исходящая от Lua.Как выяснить, когда эти ссылки сделаны?Мне нужно освободить эту память, чтобы избежать оставленных выделений памяти, оставленных в пространстве.Единственное, что приходит мне в голову, - это использовать какой-то отладчик Lua, чтобы следить за не nil указателями Lua.

Если бы я знал только, какая ссылка Lua содержит указатель, я мог бы выпустить его вручную.

Ответы [ 2 ]

2 голосов
/ 01 февраля 2012

Ваш вопрос был немного странно сформулирован.Но, насколько я понимаю, в вашем Lua-скрипте есть ссылки на объекты, размещенные во внешнем коде.И пока у Lua есть эти ссылки, внешний код не освободит эти ресурсы.И вы считаете, что эти ресурсы должны быть освобождены.

Первое, что вы должны проверить, это то, что ваш код интерфейса Lua использует метаметоды для правильной очистки ссылок.То есть, когда Lua завершает работу со ссылкой на объект, к нему прикрепляется метаметод (__gc), который сообщает внешнему коду, что Lua завершает работу с объектом.

В остальной части этого поста я будуПредположим, что этот код существует и работает правильно.Вы должны проверить это сами.

Учитывая это предположение, то, что вы видите, происходит по одной из двух причин:

  1. Ваш код Lua завершил использование всех своих ссылок, но еще не убрал их.Под этим я подразумеваю, что сценарии Lua больше не имеют ссылок ни на какие локальные переменные, глобальные переменные и т. Д. В этом случае получилось так, что сборщик мусора Lua просто еще не запустил и не очистил вещи.Так что вам нужно сделать это с lua_gc(L, LUA_GCCOLLECT, 0);.Если это так, то после запуска этой функции все ссылки из Lua должны были быть очищены.

  2. Ваш код Lua по-прежнему имеет активные ссылки на скрывающиеся вокруг внешние объекты.

Трудно разобраться с делом № 2.Кодекс Lua несет ответственность за ... ответственность.Он должен хранить ссылки, когда он должен ссылаться на вещи, а затем забыть об этих ссылках.Под этим я подразумеваю не хранить значение в нелокальной переменной (и под «нелокальной», я также имею в виду избегать локальных переменных, которые используются определениями вложенных функций).

Нетозначает найти, где эти ссылки еще существуют;в конце концов, значения Lua не обязательно имеют имя.Кроме того, Lua не дает возможности перебирать каждую возможную переменную в lua_State.Даже если бы это было так, , конечно, не было бы возможности просто убрать эти ссылки.В конце концов, код Lua может все еще касаться их.Если вы отключите их, код Lua будет аварийно завершен, когда он попытается связаться с этими объектами.Поэтому, даже если бы вы могли делать то, что хотели, это было бы контрпродуктивно.

Я бы предложил один из трех способов борьбы с этим:

  1. Упражнение по дисциплине вваш сценарий.Убедитесь, что вы знаете, где хранятся все ваши объекты, отличные от Lua.Убедитесь, что эти объекты выпущены, когда они должны быть.Знайте, куда вы помещаете эти внешние объекты, и убедитесь, что они выпущены вовремя.Под «выпущенным» я имею в виду просто перезаписать их значение с помощью nil.

  2. Создайте слой изоляции между вашим сценарием и вашим исходным кодом.Вместо того, чтобы напрямую указывать указатели Lua на объекты Cocos2D-X, укажите указатели на специальный объект, который может содержать ссылку на объект Cocos2D-X.Таким образом, вы можете контролировать, когда эти объекты будут освобождены напрямую, сказав этому объекту управления удалить его ссылку.Если Lua вызывает пустой управляющий объект, функция вернет ... что-то безобидное (чтобы вы не потерпели крах).Очевидно, у Lua должна быть функция, позволяющая определить, является ли это действительным объектом управления.

  3. Делайте все, что хотите в Lua, но затем уничтожайте все состояние Lua, когда придет время освободить ресурсы.Ваш текущий метод очень мелкозернистый.Луа создает некоторые ресурсы, и Луа решает, когда они уходят.Более строгая схема управления ресурсами будет заключаться в том, чтобы сценарии Lua загружали некоторые ресурсы и справочные ресурсы.Но когда приходит время уничтожить все эти ресурсы, вы просто lua_close сами lua_State.Это освободит все ссылки, освобождая, таким образом, эти ресурсы.Проблема решена.

0 голосов
/ 05 июня 2013

Я тоже наткнулся на эту проблему.

К сожалению, Cocos2d-x может уничтожать объекты CCObject, несмотря на то, что в скриптовом движке Lua есть ссылки на объект. Похоже, переплет не идеален.

Вы можете проверить это, создав, например, CCNode в статическом пакете, затем добавление другого CCNode к сцене, затем удаление его (запуск очистки), затем ожидание обновления кадра. Несмотря на наличие действительной ссылки lua, исходный объект CCNode пропадет, и попытки вызвать методы в нем в Lua приведут к ошибкам, несмотря на объект ~ = nil.

Вы можете обойти это, создав объект CCMutableArray_CCObject__ и добавив в него объекты CCObject. Это увеличивает количество ссылок этих объектов, и CCMutableArray_CCObject__ не будет gc'ed без ссылки lua, также gc'ed.

...