Может ли этот код вызвать утечку памяти?

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

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" не используется ни в одном из приведенных выше кодов, поэтому я думаю, что оба они вызывают утечку памяти.

Ответ 1

В вашем 1000 Movieclips будет ссылка на вашу функцию onClick. А не наоборот. Поэтому, если вы сомневаетесь в том, что ваш 1000 Movieclips получит 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 в качестве функции прослушивателя потребление памяти будет увеличиваться в каждом кадре.

Ответ 2

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

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

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

Обратите внимание, что прослушиватели событий ARE мусор собирает погоду, там есть слабая ссылка или нет, пока удаляемый объект удаляется первым. Поэтому в обоих случаях они никогда не вызовут утечки памяти. Я прошу OP отменить мой ответ как правильный и дать кредит/правильный ответ + upvotes на @Malyngo.

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

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

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

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

Резюме статьи:

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

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

Лучшее решение:

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

Обновить снова

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

Ответ 3

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

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

Как и при утечке памяти, объекты будут оставаться в памяти.