2011-07-04 28 views
5

Bản sao có thể xảy ra:
Is it possible to have a memory leak in managed code? (specifically C# 3.0)
Memory Leak in C#Làm thế nào để tạo ra một rò rỉ bộ nhớ trong C#/NET

Có một câu hỏi tương tự trên này ngày hôm qua, nhưng đối với Java, vì vậy tôi quan tâm - những gì nó cần để tạo ra một rò rỉ bộ nhớ trong C#/.NET (mà không sử dụng không an toàn)?

+1

Một số câu trả lời trong chuỗi này là chính trị, ví dụ thực tế xem tại đây: http://smartbear.com/support/articles/aqtime/net-allocation-profiler/ - "Rõ ràng, trình xử lý này không bị xóa khỏi sự kiện đã cho dẫn đến rò rỉ". –

Trả lời

12

sự kiện tĩnh; HÃY THƯỜNG GẶP, vì họ không bao giờ đi ra khỏi phạm vi.

static event EventHandler Evil; 

for(int i = 0 ; i < 1000000 ; i++) 
    Evil += delegate {}; 

Phương pháp vô danh chỉ đơn giản là một đẹp-to-có ở đây nhưng là tốt đẹp bởi vì họ cũng là một con lợn để bỏ đăng ký, trừ khi bạn có một bản sao vào một biến/lĩnh vực và đăng ký rằng.

Về mặt kỹ thuật điều này là không thực sự "rò rỉ", như bạn vẫn có thể truy cập chúng qua Evil.GetInvocationList() - tuy nhiên, khi được sử dụng với các đối tượng thường xuyên này có thể gây ra kiếp đối tượng bất ngờ, tức là

MyHeavyObject obj = ... 
... 
SomeType.SomeStaticEvent += obj.SomeMethod; 

nay là đối tượng tại obj sẽ tồn tại mãi mãi. Điều này thỏa mãn đủ rò rỉ nhận thức IMO và "ứng dụng của tôi đã chết một cái chết khủng khiếp" là đủ tốt cho tôi; p

+0

nhưng bạn vẫn có thể nhận được chúng ... không? –

+1

Có, tôi phải sửa lỗi này * một lần * trước ... chính xác một lần, bởi vì điều đó sẽ không xảy ra lần nữa =) –

+0

@Adam Ralph: Tất cả người đăng ký sẽ được lưu giữ vô thời hạn (trừ khi chưa đăng ký khỏi sự kiện) vì sự kiện là tĩnh. –

5

Khi một đối tượng đăng ký một sự kiện, đối tượng phơi bày sự kiện duy trì tham chiếu đến người đăng ký (thực tế, sự kiện, MultiCastDelegate ban đầu, nhưng nó thực hiện). Tham chiếu này sẽ ngăn không cho người đăng ký bị GC nếu tham chiếu cuối cùng (trừ trường hợp được duy trì bởi event) nằm ngoài phạm vi.

Hai câu trả lời còn lại có hoàn cảnh này hoàn toàn lạc hậu và không chính xác. Đây là một chút khó khăn để hiển thị trong một ví dụ đơn giản và thường thấy trong các dự án lớn hơn, nhưng chỉ cần nhớ rằng tham chiếu đến người đăng ký được duy trì bởi MultiCastDelegate (event) và bạn sẽ có thể suy nghĩ.

CHỈNH SỬA: Vì Marc đề cập đến phản hồi của bạn, bạn có thể tham chiếu đến đối tượng "bị rò rỉ" qua phương pháp GetInvocationList(), nhưng mã của bạn có thể không sử dụng và không thành vấn đề khi bạn gặp sự cố với số OutOfMemoryExcetion .

+0

rất đúng và tôi hoàn toàn đồng ý - nhưng chúng ta nên nhớ rằng điều này không trả lời câu hỏi –

+0

@Adam Ralph: Nó không? Nó mô tả một cách để rò rỉ bộ nhớ. Làm thế nào để tránh trả lời câu hỏi? –

+0

Tôi không đồng ý rằng bạn đang mô tả rò rỉ bộ nhớ.Một rò rỉ bộ nhớ ngụ ý rằng GC bị hỏng vì nó không giải phóng tất cả bộ nhớ được sử dụng bởi các đối tượng không được phát tán. Trong tình huống bạn mô tả các tài liệu tham khảo và thời gian sống được duy trì một cách chính xác và GC là giữ tất cả các đối tượng còn sống mà nó cần. –

1

Truy cập bộ nhớ trực tiếp được trừu tượng khỏi mã được quản lý an toàn. Có phải là một cuộc gọi đến mã không an toàn ở đâu đó để gây ra rò rỉ bộ nhớ, hoặc trong mã bạn viết hoặc trong một nguồn tài nguyên bên thứ 3 (có thể trong FCL) với một lỗi rò rỉ bộ nhớ.