2011-12-12 6 views
11

Điều này có gây ra rò rỉ bộ nhớ không?Mã này có gây ra rò rỉ bộ nhớ không?

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

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

Còn việc này thì sao?

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

"removeEventListener" không được sử dụng trong bất kỳ mã nào ở trên, vì vậy tôi nghĩ cả hai đều gây rò rỉ bộ nhớ.

+1

Không gây ra rò rỉ bộ nhớ tại thời điểm này vì bạn có thể yêu cầu tất cả 1000 movieclips có thể nhấp được.Đó là chỉ khi bạn đã làm với movieclips và muốn loại bỏ chúng khỏi bộ nhớ mà vấn đề nghe sự kiện đi vào để chơi. Câu trả lời của Ascention là chính xác nhưng từ 'sẽ' là quan trọng. – crooksy88

+0

Mọi người ở đây, tôi đã sửa chữa. Tôi sẽ không bao giờ tin vào tài liệu adobe nữa. Xem câu trả lời cập nhật của tôi. Câu trả lời hiện tại của tôi là sai. –

Trả lời

6

1000 Movieclips của bạn sẽ có một tham chiếu đến hàm onClick của bạn. Không phải hướng ngược lại. Vì vậy, nếu bạn đặt câu hỏi là nếu 1000 Movieclips của bạn sẽ nhận được GCed: Họ sẽ cuối cùng, nếu họ không có bất kỳ tài liệu tham khảo khác.

Mặt khác, tham chiếu trong movieclips của bạn vào hàm onClick của bạn sẽ giữ nguyên trạng thái đó (và đối tượng có thể thuộc về). Nếu những MC đó có bất kỳ tài liệu tham khảo nào khác để giữ cho chúng sống động.

Các mã sau đây:

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

sẽ có chức năng nghe của bạn GCed khá sớm, vì nó không có bất kỳ tài liệu tham khảo mạnh mẽ.

thiết useWeakReference true có thể được khá phù hợp nếu bạn thêm một Eventlistener đến giai đoạn bạn

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

Đoạn mã trên sẽ giữ cho đối tượng với chức năng nghe của bạn còn sống, ngay cả khi nó không có tài liệu tham khảo khác.

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

các mã trên sẽ không giữ bạn someObjectBelowIntheDisplayList sống. Nó có một tham chiếu đến sân khấu, nhưng sân khấu không có được một tài liệu tham khảo để someObjectBelowIntheDisplayList

Edit: Vui lòng thử đoạn mã sau:

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 
{ 

} 

Mã này hỗ trợ rõ ràng những gì tôi nói: Sử dụng mc .addEventListener sẽ không làm tăng mức tiêu thụ bộ nhớ. Nó sẽ ở lại khoảng 20MB trên hệ thống của tôi. Khi sử dụng đường thẳng với stage.addEventListener và sử dụng mc.onClick làm chức năng nghe, mức tiêu thụ bộ nhớ sẽ tăng lên mỗi khung hình.

+0

Mã kiểm tra tôi đã cung cấp ở trên liên tục tạo 1000 Movieclips trên mỗi khung. Nếu có rò rỉ bộ nhớ, mức tiêu thụ bộ nhớ ** sẽ tăng lên, vì tất cả các vật thể đó sẽ không được thu thập. nhưng chúng. Bằng cách thêm Movieclips làm người nghe vào sân khấu, có một rò rỉ bộ nhớ. Tham chiếu luôn là từ người điều phối đến người nghe, không phải là cách khác. vì vậy nếu không có tham chiếu đến điều phối viên nữa, nó sẽ bị phá hủy, cho dù có bao nhiêu người nghe có thể có. – Malyngo

+0

Bạn đang 100% đúng sir. Tôi đứng sửa. Tôi đã cập nhật câu trả lời của mình với nhiều thông tin hơn. Dường như adobe đã thêm thông tin mới kể từ lần cuối tôi đọc tài liệu. Tôi cũng đã yêu cầu câu trả lời của tôi được đánh dấu là không chính xác và tín dụng sẽ được trao cho bạn. –

+0

Điểm của việc thêm sự kiện ENTER_FRAME là gì. Không phải là vòng lặp đủ? –

6

cập nhật, chính xác trả lời

câu trả lời ban đầu của tôi là sai và tôi chân thành xin lỗi. Tôi sẽ để lại tất cả những lời bình luận và thông tin vượt trội của tôi để cho sự xấu hổ có thể mãi mãi nhắc nhở tôi đừng bao giờ tin tưởng bất cứ điều gì Adobe nói lại. Tài liệu hiện tại hiện tại cho biết:

"Nếu bạn không còn cần trình xử lý sự kiện, hãy xóa nó bằng cách gọi removeEventListener() hoặc các vấn đề về bộ nhớ có thể xảy ra. Bộ nghe sự kiện sẽ không tự động bị xóa khỏi bộ nhớ vì trình thu thập rác không loại bỏ người nghe miễn là đối tượng gửi tồn tại (trừ khi tham số useWeakReference được đặt thành true). "

Lưu ý rằng trình nghe sự kiện LÀ thời tiết thu thập rác có tham chiếu yếu hoặc không, miễn là đối tượng gửi đi được xóa trước tiên. Vì vậy, trong cả hai trường hợp này, chúng sẽ không bao giờ gây ra rò rỉ bộ nhớ. Tôi yêu cầu OP hủy kiểm tra câu trả lời của tôi là chính xác và đưa ra câu trả lời tín dụng/chính xác + upvotes để @Malyngo.

gốc (sai) trả lời và (mis) Thông tin Làm theo

Cả hai sẽ. Việc ràng buộc một trình nghe sự kiện sẽ tạo ra một tham chiếu mạnh mẽ đến đối tượng ban đầu, và do đó bộ thu gom rác sẽ không làm sạch nó. Bạn cần phải loại bỏ các trình lắng nghe sự kiện một cách rõ ràng hoặc chỉ định chúng như là các tham chiếu yếu, mà nên là một trong các tham số của addEventListener.

Đối với những người cho rằng người nghe sẽ không ngừng các đối tượng khác không bị thu gom rác thải

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

Tóm tắt thông tin của bài viết:

"Hãy tưởng tượng rằng người chơi của chúng tôi chết, và chúng tôi muốn cậu ấy Tuy nhiên, trình nghe sự kiện sẽ tạo một tham chiếu từ giai đoạn đến trình phát. Giai đoạn này là đối tượng hiển thị trên cùng và luôn có thể truy cập được.Vì vậy, khi quá trình quét đánh dấu chạy, trình xử lý sự kiện này cho phép bộ thu gom rác hop fr bỏ qua giai đoạn cho đối tượng trình phát của chúng tôi, ngay cả khi chúng tôi đã xóa tất cả các tham chiếu khác và xóa nó khỏi danh sách hiển thị. "

Vì vậy, vẫn có ít nhất một trường hợp trong đó người nghe sự kiện một mình, bị ràng buộc mạnh mẽ, có thể ngăn không cho đối tượng bị thu thập.

Giải pháp thực hành tốt nhất:

1) Xóa khỏi danh sách hiển thị.
2) Nếu đó là MovieClip, hãy yêu cầu dừng lại().
3) Xóa mọi trình xử lý sự kiện mà đối tượng đã tạo.
4) Xóa mọi tham chiếu trong đối tượng mẹ bằng cách đặt chúng thành rỗng.

Cập nhật lần nữa

Một rò rỉ bộ nhớ không có nghĩa là bạn sẽ thấy bộ nhớ ứng dụng liên tục phát triển. Một rò rỉ bộ nhớ cũng có thể chỉ đơn giản là mô tả bộ nhớ được phân bổ và tồn tại trong suốt vòng đời của ứng dụng, khi nó được tái chế. Một cái gì đó giống như mã kiểm tra này sẽ không dễ dàng phát hiện được. Nhưng làm cho điều này xảy ra N lần hơn một giờ trò chơi dài và tôi đảm bảo với bạn nó sẽ hiển thị. Tôi đã có tình huống tương tự xảy ra với một thuật toán mã hóa tôi đã viết một lần. Sau một thời gian, ứng dụng của tôi bắt đầu chugging với tốc độ 10 khung hình/giây, vì VM đã ăn hết một tấn bộ nhớ mà nó không thực sự sử dụng nữa nhưng nó vẫn đang quản lý nó.

1

Cả hai ví dụ đều giống nhau, vì ActionScript dựa trên ecmascript 3 không có phạm vi khối.

chỉnh sửa: Hãy để tôi cụ thể hơn: Không có phạm vi chặn, nhưng có phạm vi chức năng trong ActionScript.

Như với rò rỉ bộ nhớ, các đối tượng sẽ ở trong bộ nhớ.

+2

"Không có phạm vi chặn" là sai. Nếu bạn muốn nói rằng phạm vi không mang về phân bổ bộ nhớ và phân bổ de đó là một câu chuyện khác nhau nhưng chỉ đơn giản nói rằng không có phạm vi khối chính nó là sai. –

+0

Tôi thực sự sẽ nói rằng nó là sự thật miễn là bạn không tính một chức năng như là một phạm vi khối và xử lý nó như là một phạm vi tất cả của riêng mình. (Mà một lần nữa, về mặt kỹ thuật đúng). – WORMSS

+6

Tôi nghĩ những gì muốn nói JNissi, là AS3 sử dụng biến hoán để khai báo một biến bên trong hay bên ngoài vòng lặp có cùng tác dụng;) – Patrick