관리 메뉴

IT & Life

.Net 어플리케이션(applications)에서 메모리 누출을 피하는 방법 본문

프로그래밍/ASP.NET & C#

.Net 어플리케이션(applications)에서 메모리 누출을 피하는 방법

미운앙마 2017. 11. 17. 23:19

 


.Net에서 메모리 누수의 원인을 알아보고,이를 탐지하는 방법과 응용 프로그램에서이를 방지하는 방법

 


C 또는 C ++ 응용 프로그램을 개발했다면 의심의 여지없이 메모리 누수와 함정에 대해 알고있을 것입니다. .Net CLR이 개발자의 메모리 관리를 추상화하지만 .Net 응용 프로그램에서도 메모리 누수가 발생할 수 있습니다. 이 기사에서는 .Net 어플리케이션의 메모리 누수 원인, 발견 방법 및 피해 예방 전략에 대해 살펴 보겠습니다.

 

맨 먼저 주목해야 할 것은 관리되는 힙, 관리되지 않는 힙 및 심지어 스택의 메모리 누수가있을 수 있다는 것입니다. 스택에 할당 된 메모리는 일반적으로 메소드의 실행이 완료되면 재사용됩니다. 그러나 응용 프로그램에서 스택을 과도하게 사용하고 스택 프레임이 해제되지 않는 경우가 있습니다. 이러한 조건은 나사산이 누출 될 수 있습니다.


.Net CLR (공용 언어 런타임)은 관리되는 힙에 개체를 할당하고 더 이상 응용 프로그램에서 필요하지 않을 때 해제합니다. 그러나 런타임은 도달 할 수없는 관리 힙의 오브젝트만을 릴리스합니다. 즉, 응용 프로그램에서 관리 힙의 개체에 대한 참조가있는 경우 해당 개체는 GC (가비지 수집기)에 의해 정리되지 않습니다.

 

 

즉시 오브젝트를 해제하십시오.

 

따라서 첫 번째 규칙은 필요한 것보다 오랫동안 관리 대상 개체에 대한 참조를 보관하지 않는 것입니다. 이것은 메모리 누수가 아닌 것처럼 보이지만 응용 프로그램이 필요 이상으로 참조를 보유하면 메모리 소비가 증가하고 "메모리 부족"예외가 발생할 수 있습니다.

 

범위 내에서 로컬 인 객체를 만들고 사용하는 것이 좋습니다. 개체를 사용하여 작업을 완료하면 개체를 더 이상 필요하지 않음을 GC에 알리기 위해 개체를 null로 설정할 수 있습니다. 따라야하는 황금률은 다음과 같습니다. 리소스를 늦게 확보하고 일찍 출시하십시오.

 

 

작업자 스레드를 주시하십시오.

 

부적절한 스레드 관리는 메모리 누수의 원인이 될 수도 있습니다. 가비지 수집기가 스택을 정리하지 않기 때문에 더 이상 필요하지 않은 작업자 스레드를 명시 적으로 릴리스하여 개발자가 책임지게됩니다. 작업자 스레드를 사용하여 응용 프로그램을 끝내면 즉시 종료해야합니다.

 

멀티 스레드를 사용하여 작업 할 때 파이널 라이저가 결정적이지 않기 때문에 파이널 라이저를 사용하여 리소스를 정리하면 안됩니다. 오히려 사용자 정의 Dispose메소드를 호출하여 명시 적으로 자원을 정리해야합니다 . Thread.Abort특별한 이유가 없다면 사용 하지 않는 것이 좋습니다.

 

스레드 스택에서 메모리 누수를 피하기 위해 채택 할 수있는 또 다른 전략은 동시 스레드 수를 제한하거나 스레드 풀을 사용하여 스레드 관리를 처리하는 것입니다.

 

 

정적 참조 피하기

 

정적 개체에서 참조하는 개체는 메모리에서 절대로 릴리스되지 않습니다. 정적 필드에 의해 간접적으로 참조되는 모든 객체에 대해서도 마찬가지입니다. 이러한 객체는 응용 프로그램의 수명 동안 또는 정적 객체가 null로 표시 될 때까지 둘 중 빠른 날짜가 될 때까지 메모리에 남아 있습니다. 이는 메모리 위치를 참조하는 객체 자체가 정적이기 때문입니다.

 

여기서 교훈은 절대적으로 필요한 경우가 아니면 정적 참조를 피하는 것입니다. 정적 참조를 사용할 때는 더 이상 필요하지 않을 때 null로 표시하는 것이 중요합니다. 

 

 

관리되지 않는 개체 정리

 

관리 대상 개체 (최소 개체 힙에있는 개체)는 가비지 수집기에서 정리되지만 관리되지 않는 개체는 명시 적으로 해제해야합니다. 응용 프로그램에서 파일 핸들, 데이터베이스 연결 개체 및 COM 개체와 같이 관리되지 않는 개체를 사용하는 경우 코드에서 정리되도록, 바람직하게는 Dispose메서드 를 사용하여 정리해야합니다 . 파이널 라이저는 런타임에서 호출 할 수있는 것은 아닙니다.

 

 

큰 개체 힙 조각화 피하기

 

힙 조각화가 발생하면 관리되는 메모리가 누출 될 수도 있습니다. 기본적으로 .Net 런타임은 작은 개체 힙 (SOH)과 대형 개체 힙 (LOH)의 두 가지 유형의 힙을 관리합니다. SOH에는 작은 개체 (일반적으로 크기가 85 킬로바이트 미만)가 할당되지만 LOH에는 더 큰 개체가 할당됩니다. SOH와 달리 대형 객체 힙은 압축되지 않으므로 메모리 구멍으로 인해 메모리 손실이 발생할 수 있습니다. LOH를 정리하는 방법이 있지만 개발자는 대형 객체의 메모리 할당 비용을 인식해야합니다. 큰 개체 힙을 사용하는 방법 에 대한 내 기사를 참조하십시오.

 

 

메모리 누수를 추적하는 방법

 

개체 인스턴스를 추적하고 메모리 누수를 처리하고 탐지하는 데 사용할 수있는 많은 도구가 있습니다. 이 도구는 가장 인기있는 도구입니다.

 

ANTS 프로파일 러
dotTrace
GDIView
.Net 메모리 프로파일 러
WinDbg


힙, 관리되지 않는 힙 또는 스택에서 메모리 누수를 확인하는 가장 쉬운 방법은 Windows에서 무료로 제공되는 Perfmon 도구를 사용하여 다음 성능 카운터를 검사하는 것입니다.

 

프로세스 / 개인 바이트
.Net CLR 메모리 / 모든 힙의 # 바이트
.Net CLR LocksAndThreads / 현재 논리 스레드의 수


프로세스 / 개인 바이트가 증가하고 있지만 .Net CLR 메모리가 증가하지 않는 것을 알게되면 관리되지 않는 메모리에서 메모리 누수가 발생했다고 가정 할 수 있습니다. 반대로 두 카운터가 모두 증가하는 것을 관찰하면 메모리 누수가 관리되는 메모리에 있음을 알 수 있습니다.

 

가비지 수집의 내부 구조와 메모리 관리의 복잡성을 잘 이해하면 .Net 어플리케이션에서 메모리 누출을 피할 수있는 전략을 세울 수 있습니다. 관리되는 메모리가 가비지 수집되는 방법의 복잡함이 우리에게서 추출되었지만 불필요한 메모리 소비와 불필요하게 큰 메모리 사용량을 피하기 위해 수행 할 수있는 조치가 있습니다.

 

 

 

원문 : https://www.infoworld.com/article/3236024/application-development/how-to-avoid-memory-leaks-in-net-applications.html?upd=1510928040393

Comments