Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 16.01.2013, 12:26
Волгоградец вне форума Посмотреть профиль Отправить личное сообщение для Волгоградец Найти все сообщения от Волгоградец
  № 1  
Ответить с цитированием
Волгоградец
 
Аватар для Волгоградец

блогер
Регистрация: Sep 2007
Адрес: Гамбург
Сообщений: 1,648
Записей в блоге: 12
По умолчанию Сборщик мусора. Удаляется объект, который в дисплей листе.

Привет. Заголовок немного желтоват. На самом деле код выглядит так:

Код AS3:
package {
 
	import flash.display.Sprite;
	import flash.events.MouseEvent;
 
	public class GCTest extends Sprite {
 
		public function GCTest() {
			stage.addEventListener(MouseEvent.CLICK, stageMouseClickHandler);
		}
 
		private function stageMouseClickHandler(event:MouseEvent):void {
			var a:A = new A();
			addChild(a.vis);
		}
	}
}
 
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.system.System;
 
internal class A {
 
	public var vis:Sprite = new Sprite();
 
	private const _SHAPE:Shape = new Shape();
 
	function A() {
		vis.graphics.beginFill(0xFF0000);
		vis.graphics.drawCircle(0, 0, 50);
		vis.graphics.endFill();
 
		_SHAPE.addEventListener(Event.ENTER_FRAME, entarFrameHandler);
	}
 
	private function entarFrameHandler(event:Event):void {
		trace('enter frame handler');
		System.gc();
	}
}
При клике по сцене создается объект... и тут же удаляется сборщиком мусора. Насколько я знаю принцип работы ГЦ, объект не уничтожается, если есть хотя бы одна ссылка на него. Что мы имеем тут? _SHAPE находится не в дисплей листе, но является полем класса A. vis также является полем класса A. Сам класс A наследник Object и объект этого класса создается в локальной области видимости, на него ссылок нет, т.е. он явный кандидат на уничтожение. НО! vis, который является дисплей обжектом и полем класса A находится в дисплей листе. Собственно вопрос - какой именно из этих объектов уничтожается и почему?

Старый 16.01.2013, 12:32
toFL вне форума Посмотреть профиль Найти все сообщения от toFL
  № 2  
Ответить с цитированием
toFL
Banned

Регистрация: May 2011
Адрес: +48° 27' 57.93", +35° 2' 46.02"
Сообщений: 447
Записей в блоге: 2
Отправить сообщение для toFL с помощью Skype™
Ну так все правильно. После вот этого:
Код AS3:
var a:A = new A();
addChild(a.vis);
"a.vis" будет живет долго и счастливо, так как он в дисплей листе. А вот "a" умирает, так как на него нет ни одной ссылки. GC удаляет не целостные объекты и не подмножества...а те на которые нет ссылок.

Старый 16.01.2013, 12:47
Волгоградец вне форума Посмотреть профиль Отправить личное сообщение для Волгоградец Найти все сообщения от Волгоградец
  № 3  
Ответить с цитированием
Волгоградец
 
Аватар для Волгоградец

блогер
Регистрация: Sep 2007
Адрес: Гамбург
Сообщений: 1,648
Записей в блоге: 12
Но если он его удалит, значит он должен удалить все его поля, в том числе и vis. Т.е. память, занимаемая объектами должна освободиться. Но vis на месте и я могу обращаться к нему. А что если позже что-то перезапишется на эту память?

Старый 16.01.2013, 12:53
Wolsh вне форума Посмотреть профиль Отправить личное сообщение для Wolsh Найти все сообщения от Wolsh
  № 4  
Ответить с цитированием
Wolsh
Нуб нубам
 
Аватар для Wolsh

модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
Не путайте ссылку и значение. Ссылка будет удалена, а объект останется, так как на него есть другая ссылка — в контейнере.

Добавлено через 7 минут
Код AS3:
public var vis:Sprite = new Sprite();
public var vis:Sprite — это переменная, хранящая ссылку. Это не сам спрайт. Это ссылка, где его искать.
new Sprite(); — вот собственно "сам" спрайт, создаваемый где-то в памяти. Где — сохраняется в переменной. Или не сохраняется явно, а только во внутреннем хэше контейнера:
Код AS3:
addChild(new Sprite());
__________________
Reality.getBounds(this);

Старый 16.01.2013, 13:03
Волгоградец вне форума Посмотреть профиль Отправить личное сообщение для Волгоградец Найти все сообщения от Волгоградец
  № 5  
Ответить с цитированием
Волгоградец
 
Аватар для Волгоградец

блогер
Регистрация: Sep 2007
Адрес: Гамбург
Сообщений: 1,648
Записей в блоге: 12
Wolsh, не понял. Если срабатывает ГЦ, то он именно удаляет объекты. Вот еще пример.

Код AS3:
package {
 
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.system.System;
 
	public class GCTest extends Sprite {
 
		public function GCTest() {
			stage.addEventListener(MouseEvent.CLICK, stageMouseClickHandler);
		}
 
		private function stageMouseClickHandler(event:MouseEvent):void {
			var a:A = new A();
			addChild(a.s);
 
			var s:Sprite = new Sprite();
			addChild(s);
			s.addEventListener(Event.ENTER_FRAME, test, false, 0, true);
		}
 
		private function test(event:Event):void {
			trace('inside main');
			System.gc();
		}
	}
}
 
import flash.display.Sprite;
import flash.events.Event;
import flash.system.System;
 
internal class A {
 
	public var s:Sprite = new Sprite();
 
	function A() {
		s.addEventListener(Event.ENTER_FRAME, enterFrameHandler, false, 0, true);
		s.graphics.beginFill(0x00FF00);
		s.graphics.drawCircle(0, 0, 50);
		s.graphics.endFill();
	}
 
	private function enterFrameHandler(event:Event):void {
		trace('inside A');
		System.gc();
	}
}
Тут еще интересней. s, что внутри A удалится сразу же, хотя он в дисплей листе. s, что внутри Main будет работать бесконечно долго. В чем разница между ними?

Старый 16.01.2013, 13:28
expl вне форума Посмотреть профиль Отправить личное сообщение для expl Найти все сообщения от expl
  № 6  
Ответить с цитированием
expl

блогер
Регистрация: Feb 2006
Сообщений: 1,474
Записей в блоге: 3
Цитата:
Сообщение от Волгоградец Посмотреть сообщение
Wolsh, не понял. Если срабатывает ГЦ, то он именно удаляет объекты.
Примерно можно использовать такую модель:
Объект - это кусок памяти, в котором лежат:
- вспомогательная информация
- ссылки на другие объекты (физически 4 байта)
- примитивные типы (int, Number) - физически 4, 8 байт
И вот это всё лежит в линеечку (для одного объекта)

Ссылки ссылаются на другие объекты. Т.е. удалить объект - это удалить как раз ссылки на другие и примитивные значения.

Объекты и их ссылки представляют собой не _дерево_, а _граф_
Здесь нельзя просто взять и удалить вместе с объектом те, на которые он ссылается. На эти ссылочные объекты может ссылаться кто-то ещё.

По поводу примера кода - не смотрел ещё, вообще странно.

Старый 16.01.2013, 13:35
Волгоградец вне форума Посмотреть профиль Отправить личное сообщение для Волгоградец Найти все сообщения от Волгоградец
  № 7  
Ответить с цитированием
Волгоградец
 
Аватар для Волгоградец

блогер
Регистрация: Sep 2007
Адрес: Гамбург
Сообщений: 1,648
Записей в блоге: 12
Цитата:
Здесь нельзя просто взять и удалить вместе с объектом те, на которые он ссылается. На эти ссылочные объекты может ссылаться кто-то ещё.
Вот здесь немного проясняется. Я думал, что ГЦ просто не может убить объект, внутри которого есть "живые" объекты. Оказывается может.

Пример, да, странный. У меня еще парочка необъяснимых имеется.

Старый 16.01.2013, 14:40
iflamberg вне форума Посмотреть профиль Отправить личное сообщение для iflamberg Найти все сообщения от iflamberg
  № 8  
Ответить с цитированием
iflamberg
 
Аватар для iflamberg

Регистрация: Jan 2009
Сообщений: 1,651
Пример не странный, пример реальный. Я впервые столкнулся с таким удалением, когда делал игрушку, которая пачкой loader'ов загружала множество кусочков карты по 100 на 100 пикселей. Так вот я просто создавал в теле функции loader'ы и сразу кидал на сцену, нигде не хранил. И на некоторых компьютерах я увидел, что объекты лоадера ГЦ съедает даже еще до того, как картинка загрузилась. Причем, не очень уже хорошо помню, давно это было, но уверен, что на все загрузчики были навешаны слушатели, и не weak, и все равно ГЦ их съедал. Решил проблему хранением массива этих загрузчиков в классе, пока они все не загрузились.
__________________
мой пустой блог

Старый 16.01.2013, 16:00
expl вне форума Посмотреть профиль Отправить личное сообщение для expl Найти все сообщения от expl
  № 9  
Ответить с цитированием
expl

блогер
Регистрация: Feb 2006
Сообщений: 1,474
Записей в блоге: 3
Цитата:
на все загрузчики были навешаны слушатели, и не weak, и все равно ГЦ их съедал.
Всё правильно, он не сьёдал бы их, только если бы слушатель принадлежал самому лоадеру и Вы бы повесили его слушатель на объект, который не подлежал бы сборке мусора.

А так вы навесили слушатель - т.е. добавили ссылку на себя в лоадер - как это должно помешать его сборке?

По порядку:
Код AS3:
private function stageMouseClickHandler(event:MouseEvent):void {
			var a:A = new A();
			addChild(a.vis);
}
1. Вы создали экземпляр A
2. Вы взяли у экземпляра A vis и добавили его в список отображения
3. Вы нигде не сохранили ссылку на сам экземпляр A (функция отработала - ссылок на экземпляр A не осталось, остался только vis в списке отображения)
Что должно получиться:
- ничего не мешает собрать GC экземпляр A
- GC не может собрать vis.
Код AS3:
public var vis:Sprite = new Sprite();
 
	private const _SHAPE:Shape = new Shape();
 
	function A() {
		vis.graphics.beginFill(0xFF0000);
		vis.graphics.drawRect(-25, -25, 50, 50);
		vis.graphics.endFill();
 
		_SHAPE.addEventListener(Event.ENTER_FRAME, entarFrameHandler);
	}
3. Вы вешаете слушатель не на vis, а на _SHAPE
4. _SHAPE на сцену не добавляется
5. на _SHAPE ссылается экземпляр A, на который вы не сохранили никаких ссылок
Что должно произойти:
- Экземпляр _SHAPE должен быть снесён сборщиком мусора

Вывод: Хороший пример, демонстрирующи работу GC и никакой мистики!


Последний раз редактировалось expl; 16.01.2013 в 16:19.
Старый 16.01.2013, 16:18
iflamberg вне форума Посмотреть профиль Отправить личное сообщение для iflamberg Найти все сообщения от iflamberg
  № 10  
Ответить с цитированием
iflamberg
 
Аватар для iflamberg

Регистрация: Jan 2009
Сообщений: 1,651
Да, хороший пример, в мемориз однозначно.
__________________
мой пустой блог

Создать новую тему Ответ Часовой пояс GMT +4, время: 08:27.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 08:27.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.