내용 보기
작성자
관리자 (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
