Суббота, 20.04.2024, 00:58
Приветствую Вас Гость | RSS
Главная | Каталог статей | Регистрация | Вход
Меню сайта
Категории каталога
BlitzMax [14]
Blitz3D [9]
BlitzPlus [0]
Xna [1]
DarkBasic [0]
Общее [3]
Наш опрос
Слушаете ли вы музыку?
1. Да
2. Иногда
3. Нет
Всего ответов: 25
Форма входа
Поиск
Друзья сайта
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Статьи
Главная » Статьи » BlitzMax

Перевод туториала о менеджере памяти в БлитцМакс (1.14)
Как многие заметили в БлитцМаксе нет команды Delete , которая была в Блитц3Д. И это очень сильно путает людей, которые решили перейти на Макс.

ОСНОВЫ
----------
Давайте сначала рассмотрим, что же делает команда Delete в Blitz3D. Она делает 2 вещи.
1) Объект удаляется из внутреннего листа объектов.
2) Память объекта освобождается и возвращается системе. Это называется Деаллокацией (Deallocation)

Шаг 1 важен, т.к. в Блитц3Д все объекты добавляются в системные глобальные списки (свет в свой, меши в свой, звуки в свой и т.д.)

Шаг 2 важен для предотвращения утечек памяти. Утечка – это когда ваша программа выделяет память, использует ее, а потом не освобождает ее (деаллокирует) когда она больше не нужна и выделяет новые куски памяти под другие задачи. И в итоге память рано или поздно заканчивается.

В БлитцМаксе отсутствует система глобальных списков. Т.е. теперь пользователь должен сам следить за своими объектами. Если вы добавляете объект в связанный список, то вы сами должны его удалить из него как только объект не нужен!

Если Вы хотите достигнуть похожести с Блитц3Д в плане хранения объектов, то это просто. Используйте ListAddLast сразу после того как создали очередной объект с помощью new и используйте ListRemove перед Delete… упс, а Delete ведь нет ! Используйте ListRemove ВМЕСТО delete.

Это все оставляет открытым вопрос об деаллокации памяти, используемой объектом. Этим в БлитцМакс заведует функция FlushMem. Она автоматически находит мертвые объекты (которые уже больше не могут быть использованы в вашей программе и уничтожает их) и освобаждает память, используемую ими.

FlushMem лучше всего распологать в конце главного цикла программы и в местах возможного появления большого кол-ва неиспользуемых объектов ( например при загрузке или перезагрузке уровня).

Заметьте , что проблема освобождение неиспользуемых объектов не связана никоим образом с проблемой хранения объектов в связанных списках. Но, если Вы забудете убрать объект из списка, то он будет постоянно живым (live), т.е. FlushMem будет думать, что он все еще используется программой и не будет удалять его из памяти. Это примероно тоже, что и забывание сделать Delete в Блитц3Д.

Еще одна проблема в БлитцМакс – возможность присваивать объект переменным типа Int. Эта возможность существует в основном для начинающих.

Вместо
Local image1:TImage=LoadImage( "somepic.png" ) 'Нормальное назначение объекта объекту...
Вы можете написать
Local image2=LoadImage( "somepic.png" ) 'назначаем объект переменной типа Инт

Однако, т.к. FlushMem находит только мертвые ОБЪЕКТЫ, а не переменные типа Int, то вы сами должны удалить память используя Rlease. Т.е. вы должны будете написать
Release image2
для удаления памяти занимаемой картинкой.

Release похожа на функции из Блитц3Д – FreeImage (или FreeSound, FreeThis, FreeThat).

Хорошей практикой будет ВООБЩЕ не использовать Инт переменные для объектов ! (меньше будет потом головной боли!)

***** The nitty gritty part 1 : dead objects *****

Что такое мертвые объекты ? Мертвые обекты – такие объекты , которые никак не могут быть использованы Вашей программой, т.к. их «не видят» живые объекты. Т.е. на них не ссылается ни одна переменная типа Объект !

Local p:MyType=New MyType 'allocate object 1
p\somefield = 10 `объект MyType живой, т.к. на него ссылается переменная p и мы с помощью нее может «достать» содержимое объекта !
P = null
Все ! к памяти объекта мы теперь дотянуться не можем ! Т.к. ни одна переменная уже не ссылается на выделенную память под объект ! И теперь команда FlushMem освободит выделенную память !

Local p:MyType=New MyType 'allocate object 1
Local q:MyType=New MyType 'allocate object 2
p=q ' первый выделнный объект умер, т.к. на нее уже не ссылается переменная p. Она уже ссылается на объект на который ссылается q ! теперь, чтобы 2й объект «умер» надо «затереть» ссылки на него !
P = null
Q = null
Теперь и второй объект «умер» и FlushMem удалит память обоих.

Как Вы наверное заметили, можно использовать конструкцию SomeObj = null , чтобы форсировать удаление объекта. Но это не всегда нужно. Например в функциях, где используются локальные переменные

Function SomeFunc()
Local p:MyType=New MyType

… что-то делаем ….
EdnFunction

После того, как программа выйдет из этой функции переменная переменная p будет удалена и соответственно объект на который она ссылалась станет не доступен для программы… и соответственно, в ближайший вызов FlushMem будет удален !

И еще очень важный момент !

Function Test
a:MyType=New MyType
a = null
FlushMem()
End Function

p:MyType=New MyType
p = null
Test()

И вот тут вас ждет утечка ! FlushMem удаляет мертвые объекты только там, где был вызван ! в данном случае будет удален только объект a ! Располагайте FlushMem в конце главного цикла вашей программы и это поможет Вам избежать утечек ( но это не мешает располагать эту функцию и в других местах)

Категория: BlitzMax | Добавил: JohnK (24.03.2007) | Автор: Progs
Просмотров: 1197 | Комментарии: 1
Всего комментариев: 1
1 JohnK  
0
если у вас версия BMax больше чем 1,14, заменяйте FlushMem() на GCCollect().

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Copyright JohnK© 2024