Потерянные ссылки в Lua

Возникла проблема с объектами, которые больше не нужны, но все еще имеют ссылки. Результат: размер выделенной памяти постоянно растет из-за не собранных объектов.

Как решить такого рода проблему? Есть ли способ найти объекты только с одной ссылкой или объекты с временем жизни больше некоторого значения? Или любое другое решение?

Использование Lua 5.1 и C++ с luabind.

Спасибо.


person kFk    schedule 17.12.2009    source источник
comment
Вы случайно не храните или не пропускаете экземпляры luabind::object?   -  person sbk    schedule 17.12.2009
comment
Может быть, сохраняя. Утечек нет, потому что все экземпляры luabind::object создаются в стеке, а в коде C++ таких утечек нет.   -  person kFk    schedule 18.12.2009


Ответы (2)


Как кто-то упоминает здесь, вы можете попробовать использовать слабые таблицы.

Если у вас есть такой код:

myListOfObjects = {}
...
table.insert(myListOfObject, anObject)

Затем, как только anObject перестанет использоваться, он никогда не будет освобожден, поскольку myListOfObjects все еще ссылается на него.

Вы можете попробовать удалить ссылку в myListOfObjects (установив для ссылки значение nil), но более простым решением будет объявить myListOfObjects слабой таблицей:

myListOfObjects = {}
setmetatable(myListOfObjects, { __mode = 'v' }) --myListOfObjects is now weak

Учитывая, что setmetatable возвращает ссылку на изменяемую ею таблицу, вы можете использовать эту более короткую идиому, которая делает то же самое, что и предыдущие две строки:

myListOfObjects = setmetatable({}, {__mode = 'v' }) --creation of a weak table
person kikito    schedule 18.12.2009
comment
Слабые таблицы — хороший механизм, но как найти подходящие объекты для использования в слабых таблицах? В проекте около 2 Мб lua-кода, и проблематично найти, какие объекты не освобождены и все еще имеют ссылку. Преобразование всех таблиц в слабые таблицы приведет к преждевременному уничтожению объектов. Кроме того, таблицы в основном используются для того, чтобы владеть объектами и освобождать их только тогда, когда это необходимо. Проблема в том, что не все ссылки опубликованы, и я не могу их найти. - person kFk; 19.12.2009
comment
Если вы не уверены в том, какие таблицы должны быть слабыми, то ваш единственный способ работы — установить для всех ссылок значение nil, когда они перестанут быть полезными. Я рекомендую вам реализовать метод деструктора для всех ваших классов (типов таблиц). Этот метод деструктора следует вызывать для объектов, которые больше не нужны, и приравнивать их ссылки к нулю. Кроме того, для списка объектов реализуйте метод liberate, который присваивает nil ссылкам. - person kikito; 21.12.2009

Я не уверен в интеграции его с C++, но похоже, что сборщику мусора не дают возможности работать.

В вашем lua вы можете попробовать явно вызвать его и посмотреть, поможет ли это. В ядре API есть функция collectgarbage(opt [, arg]).

person Bryan McLemore    schedule 17.12.2009
comment
Сборка мусора работает периодически и хорошо справляется со своей задачей. Но он не собирает объекты с существующими ссылками. Таких объектов много и я не могу их найти. - person kFk; 17.12.2009
comment
Вы страдаете от проблем с циклическими ссылками? - person Bryan McLemore; 17.12.2009
comment
Правильно ли lua решает циклические ссылки? Если нет, то это может быть причиной. - person kFk; 18.12.2009
comment
Вы пробовали использовать слабые таблицы? - person Dave Berk; 18.12.2009
comment
Я не уверен, делают они это по умолчанию или нет. Я привык работать внутри WoW, в котором, как мне кажется, реализована измененная реализация сборщика мусора. Использование слабых ссылок, как упомянул Дэйв, может помочь вам обойти это. - person Bryan McLemore; 18.12.2009
comment
Проблема в том, чтобы найти, где использовать слабые таблицы. Пожалуйста, смотрите мой ответ в комментариях к egarcia. - person kFk; 19.12.2009