Game Maker - создание игр | HellRoom Games
Ноябрь 18, 2025, 04:08:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.

Войти
Новости:
 
   Начало   Game Maker Помощь Правила форума Поиск Календарь Войти Регистрация  
Страниц: [1]   Вниз
  Печать  
Автор Тема: GMS2. Проблема утечки памяти при использовании стека и рекурсии  (Прочитано 3043 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Gorimei
Посетитель
**

Репутация: -1
Offline Offline

API: GameMaker Studio 2
Сообщений: 27



« : Декабрь 01, 2021, 22:09:45 »

Доброго времени суток человеки!
Пишу проект один и всё было хорошо до сегодняшнего вечера, пока я не обратил на вес проекта в оперативе.
В общем методом научного тыка я нашёл проблему, при этом довольно быстро. Однако я не могу понять что работает не так.
У меня есть проект в котором я собственно и разрабатывал саму идею и концепцию.
Вкратце о идее. Есть объект который родитель для интерфейса и создаёт этот интерфейс, если вдруг из этого интерфейса хотим создать ещё один, то записываем новый в стек, а при этом деактивируем все что было до.
И наоборот если хотим выйти из меню в предыдущее, то активируем то, что было ранее а текущее уничтожаем.
В общем помогите найти причину утечки...

* GUI.yyz (39.92 Кб - загружено 149 раз.)
« Последнее редактирование: Декабрь 01, 2021, 22:26:58 от Gorimei » Записан
Vixer
^^,
GM Pro user
*

Репутация: 227
Offline Offline

Пол: Мужской
Награды:
3 место в Дичайшем джеме #8За постоянность! [500 дней на форуме]2 место на HellRoom Jam #5, Контраст2 место в конкурсе 1 место в конкурсе
API: GameMaker Studio 2
Деятельность: Недопрограммист, нуб-аниматор и фиговый художник
Сообщений: 555


Уф!


WWW
« Ответ #1 : Декабрь 02, 2021, 01:18:00 »

Бегло глянул пример. Большая проблема с объектом oButton - при каждом создании этого объекта (а он у Вас создается при клике вперед и назад) создается дополнительно спрайт маски (функцией sprite_duplicate), он и сидит главным образом в памяти.
И еще где-то Вы не удаляете какую-то структуру данных - при кликах вперед всё равно идет прирост по 0.01 mb памяти, но покопаться глубже в коде, увы, уже нет времени.

P.S. То есть Вы хоть и удаляете в дальнейшем объект oButton, но спрайт - это ресурс и он не удаляется при удалении экземпляра объекта.
« Последнее редактирование: Декабрь 02, 2021, 01:23:32 от Vixer » Записан

Вииииииииииииии!
SilentPhil
Norland
GM Pro user
*

Репутация: 479
Offline Offline

Пол: Мужской
Награды:
Первое место на HellRoom Jam #7 [Hell in Your Fridge]500 сообщений!За постоянность! [50 дней на форуме]За лояльность! [+150 репутации]Настоящий игродел!Второе место на HellRoom Jam #6 [По следам Артакса]...
API: GameMaker Studio 2
Деятельность: GML, Pixel Art
Сообщений: 1363



WWW
« Ответ #2 : Декабрь 03, 2021, 11:15:01 »

Зачем вы используете delete в подобном контексте?

Код:
var strSize = (string_width(string("GUI " + string(i+1)))+16)/sprite_get_height(Sprite1)
...
dеlete strSize

Код:
var gui = instance_create_depth(x,y,0,GUI)
ds_stack_push(oGUIControl.GUIStack, gui)
oGUIControl.GUISize++
return gui
delete(gui)

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

Как написали выше, достаточно удалить sprite_dublicate, который там совершенно не нужен и оставить просто mask_index = sMask; и утечка памяти исчезнет.
Записан

         
Да, на них можно кликать.
Gorimei
Посетитель
**

Репутация: -1
Offline Offline

API: GameMaker Studio 2
Сообщений: 27



« Ответ #3 : Декабрь 03, 2021, 14:41:12 »

Замечания интересные и отчасти полезные, однако не хватает ссылок на документацию.

Зачем вы используете delete в подобном контексте?

Код:
var strSize = (string_width(string("GUI " + string(i+1)))+16)/sprite_get_height(Sprite1)
...
dеlete strSize

Код:
var gui = instance_create_depth(x,y,0,GUI)
ds_stack_push(oGUIControl.GUIStack, gui)
oGUIControl.GUISize++
return gui
delete(gui)

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

Как написали выше, достаточно удалить sprite_dublicate, который там совершенно не нужен и оставить просто mask_index = sMask; и утечка памяти исчезнет.

Я хотел бы перечислить некоторые ответы на ваше сообщение:
1. В справке я найти инфу не могу по Delete и Create, но возможно я не умею ей пользоваться.
2. На счёт дубликата понятно, и я знаю, что можно юзать mask_index.
3. Это самый важный пункт, Мне не подходит mask_index, т.к. на момент сборки игры я не могу знать на 100% какие габариты и размеры будут у кнопки. По этому я хочу задавать маску уже кодом, а не использовать готовые ресурсы.

Так же я понимаю, что я могу чего-то не знать или забыть, по этому прошу отвечать с конкретными ссылками на справочник или другие статьи, если таковые всплывают на ум. Это будет полезно не только мне но и людям которые ищут ответ на схожую проблему.
Спасибо)

И да, ещё пару слов о спрайтах. В поисках решения проблемы была найдена идея менять размер спрайта не в рисовании через draw_sprite_ext, но так же можно воспользоваться переменными размера спрайта. Я попробую проверить эту гипотезу, но не помню, в справке информации о том, что границы маски этого спрайта изменяться пропорционально.
3.

Добавлено: Декабрь 03, 2021, 14:54:33
Я так же хотел бы рассказать свои результаты по поводу эксперимента с созданием объекта.
Я сделал недавно довольно простой проект, где есть 2 объекта, один из которых это объект позволяющий создавать второй объект.
В этом первом объекте есть небольшой код который проверяет нажатие ЛКМ и так же реализован небольшой откат до следующего создания объекта.
Второй объект представляет собой просто объект со спрайтом и перегруженное событие нажатия ПКМ по себеже, при котором уничтожаем этот объект.
Остальное в проекте это 1 спрайт, 1 комната с минимальными изменениями от стандартной настройки и в комнате размещён объект "создатель", назовём его так.
Да я не уточнил то, что создаю объект я при помощи функции instance_create_layer(mouse_x,mouse_y,layer,oBox).

В общем если запустить такой проект (прикреплю во вложениях), то можно будет заметить, что если создать довольно много объектов, то память вырастает и это логично, но если моментально попробовать удалить все эти объекты, то размер занимаемой памяти не вернётся в самое начало и по сути измениться на несколько процентов от максимальной загруженности.
Вот конкретный скриншот где можно взглянуть на изменения:


* inscances.yyz (13.57 Кб - загружено 138 раз.)
« Последнее редактирование: Декабрь 03, 2021, 14:55:09 от Gorimei » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  

HellRoom Games © 2006-2012 All Rights Reserved
Powered by SMF 1.1.21 | SMF © 2013, Simple Machines
Страница сгенерирована за 0.102 секунд. Запросов: 29.