Как многие заметили в БлитцМаксе нет команды 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 в конце главного цикла вашей программы и это поможет Вам избежать утечек ( но это не мешает располагать эту функцию и в других местах)
|