내용 보기
작성자
관리자 (IP : 172.17.0.1)
날짜
2020-09-25 00:28
제목
[C#] 닷넷 응용 프로그램에서 메모리 누수가 발생할 수 있는 패턴
C# - 닷넷 응용 프로그램에서 메모리 누수가 발생할 수 있는 패턴닷넷 응용 프로그램이, GC를 내장한 CLR의 동작으로 인해 "모든 메모리"가 자동으로 회수된다는 믿음을 가지신 분들이 종종 있는데요, 물론 Native 시절만큼 new/delete를 확실하게 해야 하는 필요성은 많이 줄었지만 그래도 코딩 방식에 따라 - 너무나 당연하게 메모리 누수가 발생한다는 것을 주의해야 합니다. 간간이 이에 대한 설명을 중복적으로 하게 되는데, 게다가 한 번도 이에 관한 글을 쓴 적이 없어 이참에 한번 정리해 보려고 합니다. 8 Ways You can Cause Memory Leaks in .NET ; https://michaelscodingspot.com/ways-to-cause-memory-leaks-in-dotnet/
1. 잘못된 이벤트 핸들러 관리
using System; class Program { static void Main(string[] args) { UILayout layout = new UILayout(); while (true) { for (int i = 0; i < 1000; i++) { UIElement uiElem = new UIElement(); layout.LayoutChanged += UIElement.s_Layout_LayoutChanged; } } } } public class UILayout { public event EventHandler LayoutChanged; } public class UIElement { public static void s_Layout_LayoutChanged(object sender, EventArgs e) { } }
layout.LayoutChanged.Add(uiElem.Layout_LayoutChanged);
public class UILayout
{
public event List<EventHandler> LayoutChanged;
}
using System; class Program { static void Main(string[] args) { UILayout layout = new UILayout(); while (true) { for (int i = 0; i < 1000; i++) { UIElement uiElem = new UIElement(); layout.LayoutChanged += uiElem.Layout_LayoutChanged; } } } } public class UILayout { public event EventHandler LayoutChanged; } public class UIElement { public void Layout_LayoutChanged(object sender, EventArgs e) { } }
layout.LayoutChanged.Add(new EventHandler(uiElem, uiElem.Layout_LayoutChanged)); public class UILayout { public event List<EventHandler> LayoutChanged; }
while (true)
{
for (int i = 0; i < 1000; i++)
{
UIElement uiElem = new UIElement();
layout.LayoutChanged += uiElem.Layout_LayoutChanged;
layout.LayoutChanged -= uiElem.Layout_LayoutChanged;
}
}
2. 익명 메서드 내에서의 캡처 변수 사용
3. 정적 변수의 사용
using System.Collections.Generic; class Program { static void Main(string[] args) { while (true) { for (int i = 0; i < 100; i++) { ConsoleHelper ch = new ConsoleHelper(); } } } } public class ConsoleHelper { static List
4. 잘못된 Cache 사용
5. 잘못된 WPF 바인딩 사용
// xaml <UserControl x:Class="WpfApp.MyControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <TextBlock Text="{Binding SomeText}"></TextBlock> </UserControl> // cs public class MyViewModel { public string _someText = "memory leak"; public string SomeText { get { return _someText; } set { _someText = value; } } }
public class MyViewModel : INotifyPropertyChanged { public string _someText = "not a memory leak"; public string SomeText { get { return _someText; } set { _someText = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof (SomeText))); } } // ...[생략]... }
6. 종료하지 않는 Thread 사용
public class MyClass { public MyClass() { Timer timer = new Timer(HandleTick); timer.Change(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5)); } private void HandleTick(object state) { // do something } //...[생략]... }
7. 해제하지 못한 비관리 메모리
public class SomeClass { private IntPtr _buffer; public SomeClass() { _buffer = Marshal.AllocHGlobal(1000); } public void Dispose() { Marshal.FreeHGlobal(_buffer); } }
8. 필요한 경우 Finalizer 구현
.NET IDisposable 처리 정리 ; https://www.sysnet.pe.kr/2/0/347
|
출처1
https://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&pageno=0&detail=1&wid=12343
출처2