Будет ли этот код причиной утечки памяти? - PullRequest
11 голосов
/ 12 декабря 2011

Будет ли это причиной утечки памяти?

var mc:MovieClip ; //<<<<<<< OUTSIDE LOOP

for ( var i=0 ; i< 1000 ; i++)
{
   mc = new MovieClip() ;
   mc.addEventListener( MouseEvent.CLICK , onClick) ;
}

А что по этому поводу?

for ( var i=0 ; i< 1000 ; i++)
{
  var mc:MovieClip ; //<<<<<<< INSIDE LOOP
   mc = new MovieClip() ;
   mc.addEventListener( MouseEvent.CLICK , onClick) ;
}

«removeEventListener» не используется ни в одном из приведенных выше кодов, поэтому я думаю, что оба они вызывают утечку памяти.

Ответы [ 3 ]

6 голосов
/ 13 декабря 2011

Ваши 1000 видеоклипов будут иметь ссылку на функцию onClick.А не наоборот.Поэтому, если вы спросите, получат ли ваши 1000 видеоклипов GCed: они в конечном итоге получат, если у них не будет никакой другой ссылки.

С другой стороны, ссылка в ваших видеоклипах на вашу функцию onClick сохранит это в живых.(и объект, которому он может принадлежать).Если у этих MC есть какая-либо другая ссылка, которая будет поддерживать их.

Следующий код:

mc.addEventListener(MouseEvent.CLICK , function(ev:Event):void{  trace("I am only a poor anonymous function");  }, false, 0, true);

Очень скоро ваша функция слушателя будет GCed, поскольку она не имеет сильной ссылки.

установка useWeakReference в значение true может быть весьма уместна, если вы добавляете Eventlistener на вашу сцену

stage.addEventListener(MouseEvent.CLICK, someObjectBelowIntheDisplayList.listenerFunction);

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

someObjectBelowIntheDisplayList.addEventListener(MouseEvent.CLICK, stage.onClick)

приведенный выше код не сохранит ваш someObjectBelowIntheDisplayList в действии.Он имеет ссылку на сцену, но сцена не получает ссылку на someObjectBelowIntheDisplayList

Редактировать: пожалуйста, попробуйте следующий код:

import flash.display.MovieClip;
import flash.events.Event;

var mc:MovieClip ; //<<<<<<< OUTSIDE LOOP

function enterframe(ev:Event):void
{
    for ( var i=0 ; i< 1000 ; i++)
    {
       mc = new MovieClip() ;
       mc.onClick = function(ev:Event){};
       // Use one of the following lines, comment out the other one
       //mc.addEventListener( MouseEvent.CLICK , onClick) ; // no memory leak
       stage.addEventListener(MouseEvent.CLICK, mc.onClick); // memory will rise up and up
    }
}

this.addEventListener(Event.ENTER_FRAME, enterframe);

function onClick(ev:Event):void
{

}

Этот код явноподдерживает то, что я говорю: использование mc.addEventListener не увеличит потребление памяти.В моей системе он останется около 20 МБ.При использовании строки с stage.addEventListener и использовании mc.onClick в качестве функции прослушивателя потребление памяти будет увеличиваться с каждым кадром.

6 голосов
/ 12 декабря 2011

Обновлено, правильный ответ

Мой первоначальный ответ был неверным, и я искренне извиняюсь.Я оставлю все свои снисходительные комментарии и информацию нетронутыми, чтобы позор навсегда напомнил мне никогда не доверять тому, что Adobe снова скажет.Текущая документация теперь гласит:

"Если вам больше не нужен прослушиватель событий, удалите его, вызвав removeEventListener (), иначе могут возникнуть проблемы с памятью. Прослушиватели событий не удаляются автоматически из памяти, поскольку сборщик мусора не удаляетпрослушиватель до тех пор, пока существует диспетчерский объект (если для параметра useWeakReference не задано значение true). "

Обратите внимание, что прослушиватели событий СОБРАНЫ для сбора мусора, если естьслабая ссылка или нет, пока диспетчерский объект удаляется первым.Таким образом, в обоих случаях они никогда не вызовут утечку памяти.Я прошу ОП отменить мой ответ как правильный и дать кредит / правильный ответ + отзыв на @ Malyngo.

Оригинальный (неправильный) ответ и (неправильная) информация следует

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

Для людей, утверждающих, что слушатели не будут мешать другим объектам собирать мусор

http://gingerbinger.com/2010/07/actionscript-3-0-events-the-myth-of-useweakreference/

Краткое содержание статьи:

"Представьте, что наш игрок умирает, и мы хотим, чтобы он был очищен. Однако слушатель события создаетссылка со сцены на игрока. Эта сцена является самым верхним экранным объектом и всегда доступна. Поэтому, когда запускается процесс очистки метки, этот прослушиватель событий позволяет сборщику мусора переходить от сцены к нашему объекту игрока, даже еслимы удалили все остальные ссылки и удалили его из списка отображения. "

Таким образом, существует по крайней мере один сценарий, в котором только прослушиватель событий, строго связанный, может препятствовать объекту.

Лучшее практическое решение:

1) Снимите его с дисплея. list.
2) Если это мувиклип, скажите ему остановить ().
3) Удалите все прослушиватели событий, созданные объектом.
4) Удалите все ссылки в родительских объектах, установив для них значение null.

Обновление снова

Утечка памяти не обязательно означает, что память приложений будет постоянно расти.Утечка памяти также может просто описывать память, которая выделяется и сохраняется в течение всего срока службы приложения, когда она должна быть переработана.Нечто подобное этому тестовому коду будет не очень легко обнаружить.Но сделайте это N раз за час игры, и я гарантирую вам это покажет.У меня была такая же ситуация с алгоритмом шифрования, который я написал однажды.Через некоторое время мое приложение начало работать с частотой 10 или менее кадров в секунду, потому что виртуальная машина съела тонну памяти, которую она на самом деле больше не использовала, но все еще управляла ей.

1 голос
/ 12 декабря 2011

Оба примера одинаковы, так как actionScript основан на ecmascript 3, который не имеет области видимости блока.

edit: Позвольте мне быть более конкретным: область действия блока отсутствует, но область действия есть в ActionScript.

Как и в случае утечки памяти, объекты останутся в памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...