Windows 애플리케이션에서 메모리 누수 방지
영향을 받는 플랫폼
클라이언트 - Windows 7
서버 - Windows Server 2008 R2
설명
메모리 누수는 애플리케이션이 더 이상 필요하지 않을 때 메모리를 해제하지 못하는 버그 클래스입니다. 시간이 지남에 따라 메모리 누수는 운영 체제뿐만 아니라 특정 애플리케이션의 성능에 영향을 줍니다. 큰 누출로 인해 과도한 페이징으로 인해 허용되지 않는 응답 시간이 발생할 수 있습니다. 결국 애플리케이션과 운영 체제의 다른 부분에 오류가 발생합니다.
Windows는 프로세스 종료에 애플리케이션에서 할당한 모든 메모리를 해제하므로, 짧은 실행 애플리케이션은 전체 시스템 성능에 크게 영향을 미치지 않습니다. 그러나 서비스 또는 Explorer 플러그 인과 같은 장기 실행 프로세스의 누출은 시스템 안정성에 큰 영향을 미칠 수 있으며 시스템을 다시 사용할 수 있도록 하기 위해 사용자가 Windows를 다시 부팅하도록 강제할 수 있습니다.
애플리케이션은 여러 수단을 통해 대신 메모리를 할당할 수 있습니다. 각 할당 유형은 사용 후 해제되지 않으면 누출이 발생할 수 있습니다. 다음은 일반적인 할당 패턴의 몇 가지 예입니다.
- HeapAlloc 함수 또는 해당 C/C++ 런타임에 해당하는 malloc 또는 new를 통한 힙 메모리
- VirtualAlloc 함수를 통해 운영 체제에서 직접 할당합니다.
- Kernel32 API(예: CreateFile, CreateEvent 또는 CreateThread)를 통해 만든 커널 핸들은 애플리케이션을 대신하여 커널 메모리를 보유합니다.
- User32 및 Gdi32 API를 통해 만든 GDI 및 USER 핸들(기본적으로 각 프로세스의 할당량은 10,000개 핸들)입니다.
모범 사례
시간이 지남에 따라 애플리케이션의 리소스 소비를 모니터링하는 것은 메모리 누수 감지 및 진단의 첫 번째 단계입니다. Windows 작업 관리자를 사용하여 "커밋 크기", "핸들", "사용자 개체" 및 "GDI 개체" 열을 추가합니다. 이렇게 하면 애플리케이션에 대한 기준을 설정하고 시간이 지남에 따라 리소스 사용량을 모니터링할 수 있습니다.
다음 Microsoft 도구는 보다 자세한 정보를 제공하며 애플리케이션의 다양한 할당 유형에 대한 누출을 감지하고 진단하는 데 도움이 될 수 있습니다.
- 성능 모니터 및 리소스 모니터는 Windows 7의 일부이며 시간이 지남에 따라 리소스 사용을 모니터링하고 그래프로 나타낼 수 있습니다.
- 최신 버전의 애플리케이션 검증 도구는 Windows 7에서 힙 누출을 진단할 수 있습니다.
- Windows용 디버깅 도구의 일부인 UMDH는 지정된 프로세스에 대한 힙 메모리 할당을 분석하고 누수 및 기타 비정상적인 사용 패턴을 찾는 데 도움이 될 수 있습니다.
- Xperf는 힙 할당 추적을 지원하는 정교한 성능 분석 도구입니다.
- CRT 디버그 힙은 힙 할당을 추적하고 고유한 힙 디버깅 기능을 빌드하는 데 도움이 될 수 있습니다.
특정 코딩 및 디자인 사례는 코드의 누수 수를 제한할 수 있습니다.
- 힙 할당뿐만 아니라 커널 핸들과 같은 Win32 리소스의 경우 C++ 코드에서 스마트 포인터를 사용합니다. C++ 표준 라이브러리는 힙 할당을 위한 auto_ptr 클래스를 제공합니다. 다른 할당 형식의 경우 고유한 클래스를 작성해야 합니다. ATL 라이브러리는 힙 개체와 커널 핸들 모두에 대한 자동 리소스 관리를 위한 다양한 클래스 집합을 제공합니다.
- _com_ptr_t 같은 컴파일러 내장 기능을 사용하여 COM 인터페이스 포인터를 "스마트 포인터"로 캡슐화하고 참조 계산을 지원합니다. 다른 COM 데이터 형식에는 _bstr_t 및 _variant_t 유사한 클래스가 있습니다.
- .NET 코드의 비정상적인 메모리 사용량을 모니터링합니다. 관리 코드는 메모리 누수에 면역이 되지 않습니다. GC 누수를 찾는 방법은 "관리되는 메모리 누수 추적" 을 참조하세요.
- 웹 클라이언트 쪽 코드의 누수 패턴에 유의하세요. COM 개체와 JScript와 같은 스크립팅 엔진 간의 순환 참조는 웹 애플리케이션에서 큰 누수가 발생할 수 있습니다. "인터넷 Explorer 누수 패턴 이해 및 해결"에는 이러한 종류의 누출에 대한 자세한 정보가 있습니다. JavaScript 메모리 누수 감지기를 사용하여 코드에서 메모리 누수 디버그할 수 있습니다. Windows 7과 함께 제공되는 Windows Internet Explorer 8은 이러한 문제를 대부분 완화하지만 이전 브라우저는 여전히 이러한 버그에 취약합니다.
- 함수에서 여러 종료 경로를 사용하지 마세요. 함수 scope 변수에 할당된 할당은 함수 끝에 있는 특정 블록 하나에서 해제되어야 합니다.
- 함수의 모든 지역 변수를 해제하지 않고 코드에서 예외를 사용하지 마세요. 네이티브 예외를 사용하는 경우 __finally 블록 내에서 모든 할당을 해제합니다. C++ 예외를 사용하는 경우 모든 힙 및 핸들 할당을 스마트 포인터로 래핑해야 합니다.
- PropVariantClear 함수를 호출하지 않고 PROPVARIANT 개체를 삭제하거나 다시 초기화하지 마세요.
리소스에 대한 링크
일반적인 할당 패턴:
Microsoft 도구:
추가 링크:
- auto_ptr 클래스
- ATL(활성 템플릿 라이브러리) 메모리 클래스
- _com_ptr_t 개체
- _bstr_t 클래스
- _variant_yt 클래스
- "관리되는 메모리 누수 추적"
- "인터넷 Explorer 누수 패턴 이해 및 해결"
- "JavaScript 메모리 누수 감지기"
- 순환 메모리 누수 완화(브라우저에서):
- try-finally 문
- PROPVARIANT 구조체
- PropVariantClear 함수