커널 디버거를 사용하여 Kernel-Mode 메모리 누수 찾기
커널 디버거는 커널 모드 메모리 누수의 정확한 위치를 결정합니다.
풀 태그 지정 사용
먼저 GFlags를 사용하여 풀 태그 지정을 사용하도록 설정해야 합니다. GFlags는 Windows용 디버깅 도구에 포함되어 있습니다. GFlags를 시작하고 시스템 레지스트리 탭을 선택하고 풀 태그 지정 사용 상자를 검사 다음 적용을 선택합니다. 이 설정을 적용하려면 Windows를 다시 시작해야 합니다.
Windows Server 2003 이상 버전의 Windows에서는 풀 태그 지정이 항상 사용하도록 설정됩니다.
누수의 풀 태그 확인
누수와 연결된 풀 태그를 확인하려면 일반적으로 이 단계에서 PoolMon 도구를 사용하는 것이 가장 쉽습니다. 자세한 내용은 PoolMon을 사용하여 Kernel-Mode 메모리 누수 찾기를 참조하세요.
또는 커널 디버거를 사용하여 큰 풀 할당과 관련된 태그를 찾을 수 있습니다. 이렇게 하려면 다음 절차를 수행합니다.
!poolused 확장을 사용합니다. 페이징된 메모리 사용을 기준으로 출력을 정렬하려면 플래그 "4"를 포함합니다.
kd> !poolused 4 Sorting by Paged Pool Consumed Pool Used: NonPaged Paged Tag Allocs Used Allocs Used Abc 0 0 36405 33930272 Tron 0 0 552 7863232 IoN7 0 0 10939 998432 Gla5 1 128 2222 924352 Ggb 0 0 22 828384
메모리 사용량이 가장 많은 풀 태그를 결정합니다. 이 예제에서는 "Abc" 태그를 사용하는 드라이버가 가장 많은 메모리(거의 34MB)를 사용합니다. 따라서 메모리 누수는 이 드라이버에 있을 가능성이 가장 높습니다.
누수 찾기
누수와 관련된 풀 태그를 결정한 후 이 절차에 따라 누수 자체를 찾습니다.
ed(값 입력) 명령을 사용하여 전역 시스템 변수 PoolHitTag의 값을 수정합니다. 이 전역 변수를 사용하면 해당 값과 일치하는 풀 태그가 사용될 때마다 디버거가 중단됩니다.
PoolHitTag를 메모리 누수의 원본으로 의심되는 태그와 동일하게 설정합니다. 더 빠른 기호 확인을 위해 모듈 이름 "nt"를 지정해야 합니다. 태그 값은 little-endian 형식(즉, 뒤로)으로 입력해야 합니다. 풀 태그는 항상 4자이므로 이 태그는 단순히 A-b-c가 아니라 실제로 A-b-c-space입니다. 따라서 다음 명령을 사용합니다.
kd> ed nt!poolhittag ' cbA'
PoolHitTag의 현재 값을 확인하려면 db(메모리 표시) 명령을 사용합니다.
kd> db nt!poolhittag L4 820f2ba4 41 62 63 20 Abc
디버거는 Abc 태그를 사용하여 풀이 할당되거나 해제될 때마다 중단됩니다. 이러한 할당 또는 무료 작업 중 하나에서 디버거가 중단 될 때마다 kb (Stack Backtrace 표시) 디버거 명령을 사용하여 스택 추적을 봅니다.
이 절차를 사용하여 메모리에 상주하는 코드가 Abc 태그를 사용하여 풀을 초과 할당하는지 확인할 수 있습니다.
중단점을 지우려면 PoolHitTag 를 0으로 설정합니다.
kd> ed nt!poolhittag 0
이 태그가 있는 메모리가 할당되고 사용자가 작성한 애플리케이션 또는 드라이버에 있는 여러 다른 위치가 있는 경우 이러한 각 할당에 고유한 태그를 사용하도록 소스 코드를 변경할 수 있습니다.
프로그램을 다시 컴파일할 수 없지만 코드에서 누수를 유발할 수 있는 여러 위치 중 하나를 확인하려는 경우 각 위치에서 코드를 언어셈블하고 디버거를 사용하여 각 instance 고유한(이전에 사용되지 않은) 풀 태그를 사용하도록 메모리에 상주하는 이 코드를 편집할 수 있습니다. 그런 다음 시스템이 몇 분 이상 실행되도록 허용합니다. 시간이 지나면 디버거를 사용하여 다시 침입하고 !poolfind 확장을 사용하여 각 새 태그와 연결된 모든 풀 할당을 찾습니다.