Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Средство проверки драйверов создает проверку ошибок 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION с параметром 1, равным 0x62, при выгрузке драйвера без предварительного освобождения всех выделенных пулов. Невысвобожденные выделения памяти (также называемые утечками памяти) являются распространенной причиной снижения производительности операционной системы. Они могут фрагментировать системные пулы и в конечном итоге вызвать сбои системы.
Если у вас есть отладчик ядра, подключенный к тестовом компьютеру с проверкой драйверов, если средство проверки драйверов обнаруживает нарушение, Windows переходит в отладчик и отображает краткое описание ошибки.
>Отладка утечки памяти при выгрузке драйвера
- Используйте !analyze, чтобы отобразить сведения об ошибке
- Используйте команду расширения !verifier 3, чтобы узнать о выделении пула
- Если у вас есть символы, можно найти место, где в исходных файлах произошло выделение памяти.
- Проверка журнала выделения памяти
- Устранение утечек памяти
Используйте !analyze, чтобы отобразить информацию о сбое
Как и при возникновении любой проверки ошибок, после того как вы управляете отладчиком, лучше всего выполнить команду !analyze -v .
kd> !analyze -v
Connected to Windows 8 9600 x86 compatible target
Loading Kernel Symbols
.................................................................................
Loading User Symbols
.......................
Loading unloaded module list
........
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
DRIVER_VERIFIER_DETECTED_VIOLATION (c4)
A device driver attempting to corrupt the system has been caught. This is
because the driver was specified in the registry as being suspect (by the
administrator) and the kernel has enabled substantial checking of this driver.
If the driver attempts to corrupt the system, bugchecks 0xC4, 0xC1 and 0xA will
be among the most commonly seen crashes.
Arguments:
Arg1: 00000062, A driver has forgotten to free its pool allocations prior to unloading.
Arg2: 9707712c, name of the driver having the issue.
Arg3: 9c1faf70, verifier internal structure with driver information.
Arg4: 00000003, total # of (paged+nonpaged) allocations that weren't freed.
Type !verifier 3 drivername.sys for info on the allocations
that were leaked that caused the bugcheck.
Проверка ошибок 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION со значением параметра 1 (Arg1) 0x62 описана следующим образом:
DRIVER_VERIFIER_DETECTED_VIOLATION (C4) Arg1 Arg2 Arg3 Arg4 Причина Верификатора драйвера 0x62 Имя драйвера. Зарезервированное совокупное количество выделенной памяти, не освобождённой, включая как пул на страницах, так и нестраничного пула. Драйвер выгружает, не освободив сначала ресурсы пула. В Windows 8.1 эта ошибка также возникает, если драйвер выгрузился без первого освобождения рабочих элементов (IO_WORKITEM), выделенных с помощью IoAllocateWorkItem. Проверка ошибок с этим параметром возникает только в том случае, если параметр отслеживания пула активен. Укажите отслеживание пула (верификатор /флаги 0x8). Опция отслеживания пула включена с помощью стандартных флагов (верификатора /standard)
Используйте команду расширения !verifier 3, чтобы узнать об аллокации пула.
Для этой конкретной проверки ошибок информация, указанная в параметре 4 (Arg4), является наиболее важной. Arg4 показывает количество выделенных ресурсов, которые не были освобождены. Выходные данные команды !analyze также показывают команду расширения отладчика !verifier, которую можно использовать для отображения того, что именно выделялось. Полный результат команды !verifier 3 MyDriver.sys показан в следующем примере:
kd> !verifier 3 Mydriver.sys
Verify Flags Level 0x000209bb
STANDARD FLAGS:
[X] (0x00000000) Automatic Checks
[X] (0x00000001) Special pool
[X] (0x00000002) Force IRQL checking
[X] (0x00000008) Pool tracking
[X] (0x00000010) I/O verification
[X] (0x00000020) Deadlock detection
[X] (0x00000080) DMA checking
[X] (0x00000100) Security checks
[X] (0x00000800) Miscellaneous checks
[X] (0x00020000) DDI compliance checking
ADDITIONAL FLAGS:
[ ] (0x00000004) Randomized low resources simulation
[ ] (0x00000200) Force pending I/O requests
[ ] (0x00000400) IRP logging
[ ] (0x00002000) Invariant MDL checking for stack
[ ] (0x00004000) Invariant MDL checking for driver
[ ] (0x00008000) Power framework delay fuzzing
[ ] (0x00040000) Systematic low resources simulation
[ ] (0x00080000) DDI compliance checking (additional)
[ ] (0x00200000) NDIS/WIFI verification
[ ] (0x00800000) Kernel synchronization delay fuzzing
[ ] (0x01000000) VM switch verification
[X] Indicates flag is enabled
Summary of All Verifier Statistics
RaiseIrqls 0x0
AcquireSpinLocks 0x0
Synch Executions 0x0
Trims 0x0
Pool Allocations Attempted 0x2db1a
Pool Allocations Succeeded 0x2db1a
Pool Allocations Succeeded SpecialPool 0x2db1a
Pool Allocations With NO TAG 0x0
Pool Allocations Failed 0x0
Current paged pool allocations 0x0 for 00000000 bytes
Peak paged pool allocations 0x0 for 00000000 bytes
Current nonpaged pool allocations 0x3 for 00001058 bytes
Peak nonpaged pool allocations 0x13 for 0004A4A0 bytes
## Driver Verification List
MODULE: 0x84226b28 MyDriver.sys (Loaded)
Pool Allocation Statistics: ( NonPagedPool / PagedPool )
Current Pool Allocations: ( 0x00000003 / 0x00000000 )
Current Pool Bytes: ( 0x00001058 / 0x00000000 )
Peak Pool Allocations: ( 0x00000013 / 0x00000000 )
Peak Pool Bytes: ( 0x0004A4A0 / 0x00000000 )
Contiguous Memory Bytes: 0x00000000
Peak Contiguous Memory Bytes: 0x00000000
Pool Allocations:
Address Length Tag Caller
---------- ---------- ---- ----------
0x982a8fe0 0x00000020 VMdl 0x9a3bf6ac MyDriver!DeviceControlDispatch
0x8645a000 0x00001008 mdrv 0x9a3bf687 MyDriver!DeviceControlDispatch
0x9a836fd0 0x00000030 Vfwi 0x9a3bf6ed MyDriver!GetNecessaryObjects
Например, драйвер, MyDriver.sys, имеет два выделения памяти и один рабочий элемент ввода-вывода, который не был освобожден должным образом. Каждый список показывает адрес текущего выделения, размер, используемый тег пула и адрес в коде драйвера, в котором был выполнен запрос на выделение. Если символы загружены для данного драйвера, они также будут отображать имя функции рядом с адресом вызывающего.
Из отображаемых тегов только один (для выделения по адресу 0x8645a000) был предоставлен самим драйвером (mdrv). VMdl используется всякий раз, когда драйвер, проверяемый средством проверки драйверов, вызывает IoAllocateMdl. Аналогичным образом тег Vfwi используется всякий раз, когда драйвер, проверяемый проверяемым драйвером, выполняет запрос на выделение рабочего элемента с помощью IoAllocateWorkItem.
Если у вас есть символы, можно найти место, где в исходных файлах произошло выделение памяти.
Если символы загружаются для драйвера, если эти символы содержат сведения о номере строки, можно использовать команду lnCallerAddress для отображения строки, в которой был выполнен вызов. Эти выходные данные также будут отображать смещение в функции, которая сделала выделение.
kd> ln 0x9a3bf6ac
d:\coding\wdmdrivers\mydriver\handleioctl.c(50)+0x15
(9a3bf660) MyDriver!DeviceControlDispatch+0x4c | (9a3bf6d0) MyDriver!DeviceControlDispatch
kd> ln 0x9a3bf687
d:\coding\wdmdrivers\mydriver\handleioctl.c(38)+0x12
(9a3bf660) MyDriver!DeviceControlDispatch+0x27 | (9a3bf6d0) MyDriver!DeviceControlDispatch
kd> ln 0x9a3bf6ed
d:\coding\wdmdrivers\mydriver\handleioctl.c(72)+0xa
(9a3bf6d0) MyDriver!GetNecessaryObjects+0x1d | (9a3bf71c) MyDriver!GetNecessaryObjects
Проверка журнала выделения памяти
Средство проверки драйверов также сохраняет циклический журнал всех выделений памяти, сделанных в пространстве ядра при включении отслеживания пула. По умолчанию сохраняются последние 65 536 (0x10000) выделенных ресурсов. Когда создаётся новое выделение, самое старое выделение в журнале перезаписывается. Если выделения были сделаны недавно перед сбоем, возможно, можно получить дополнительные сведения о выделении, чем показано выше, в частности адрес потока и кадры стека ядра во время выделения.
Доступ к этому журналу можно получить с помощью команды !verifier 0x80AddressOfPoolAllocation. Обратите внимание, что в журнале перечислены все выделения и освобождения для данного адреса. Чтобы отменить или остановить отображение истории журнала, используйте сочетания клавиш: Ctrl+Break с WinDbg и Ctrl+C с KD.
kd> !verifier 0x80 0x982a8fe0
Log of recent kernel pool Allocate and Free operations:
There are up to 0x10000 entries in the log.
Parsing 0x00010000 log entries, searching for address 0x982a8fe0.
#
Pool block 982a8fe0, Size 00000020, Thread 9c158bc0
81b250cd nt!IovAllocateMdl+0x3d
8060e41d VerifierExt!IoAllocateMdl_internal_wrapper+0x35
81b29388 nt!VerifierIoAllocateMdl+0x22
9a3bf6ac MyDriver!DeviceControlDispatch+0x4c
9a3bf611 MyDriver!NonPNPIRPDispatch0x51
9a3bf05a MyDriver!AllIRPDispatch+0x1a
80611710 VerifierExt!xdv_IRP_MJ_DEVICE_CONTROL_wrapper+0xd0
81b3b635 nt!ViGenericDispatchHandler+0x2d
81b3b784 nt!ViGenericDeviceControl+0x18
81b24b4d nt!IovCallDriver+0x2cc
81703772 nt!IofCallDriver+0x62
8191165e nt!IopSynchronousServiceTail+0x16e
81915518 nt!IopXxxControlFile+0x3e8
kd> !verifier 0x80 0x8645a000
Log of recent kernel pool Allocate and Free operations:
There are up to 0x10000 entries in the log.
Parsing 0x00010000 log entries, searching for address 0x8645a000.
#
Pool block 8645a000, Size 00001000, Thread 9c158bc0
8060ee4f VerifierExt!ExAllocatePoolWithTagPriority_internal_wrapper+0x5b
81b2619e nt!VerifierExAllocatePoolWithTag+0x24
9a3bf687 MyDriver!DeviceControlDispatch+0x27
9a3bf611 MyDriver!NonPNPIRPDispatch0x51
9a3bf05a MyDriver!AllIRPDispatch+0x1a
80611710 VerifierExt!xdv_IRP_MJ_DEVICE_CONTROL_wrapper+0xd0
81b3b635 nt!ViGenericDispatchHandler+0x2d
81b3b784 nt!ViGenericDeviceControl+0x18
81b24b4d nt!IovCallDriver+0x2cc
81703772 nt!IofCallDriver+0x62
8191165e nt!IopSynchronousServiceTail+0x16e
81915518 nt!IopXxxControlFile+0x3e8
81914516 nt!NtDeviceIoControlFile+0x2a
kd> !verifier 0x80 0x9a836fd0
Log of recent kernel pool Allocate and Free operations:
There are up to 0x10000 entries in the log.
Parsing 0x00010000 log entries, searching for address 0x9a836fd0.
#
Pool block 9a836fd0, Size 00000030, Thread 88758740
8151713d nt!IovAllocateWorkItem+0x1b
84a133d9 VerifierExt!IoAllocateWorkItem_internal_wrapper+0x29
8151b3a7 nt!VerifierIoAllocateWorkItem+0x16
9a3bf6ed MyDriver!GetNecessaryObjects+0x1d
9a3bf620 MyDriver!NonPNPIRPDispatch0x51
9a3bf05a MyDriver!AllIRPDispatch+0x1a
84a16710 VerifierExt!xdv_IRP_MJ_DEVICE_CONTROL_wrapper+0xd0
8152d635 nt!ViGenericDispatchHandler+0x2d
8152d784 nt!ViGenericDeviceControl+0x18
81516b4d nt!IovCallDriver+0x2cc
810f5772 nt!IofCallDriver+0x62
8130365e nt!IopSynchronousServiceTail+0x16e
81307518 nt!IopXxxControlFile+0x3e8
Устранение утечек памяти
Эта проверка ошибок средства проверки драйверов предназначена для предотвращения утечки памяти ядра драйвера. В каждом случае правильное исправление заключается в том, чтобы определить существующие пути кода, в которых выделенные объекты не освобождаются, и убедиться, что они освобождены должным образом.
Средство проверки статических драйверов — это средство, которое сканирует исходный код драйвера Windows и сообщает о возможных проблемах, имитируя выполнение различных путей кода. Средство проверки статических драйверов — это отличная утилита разработки, которая помогает выявлять такие проблемы.
Другие методы, которые можно использовать, включая сценарии, в которых средство проверки драйверов не участвует, см. в разделе "Поиск утечки памяти Kernel-Mode".
Связанные темы
Поиск утечки памяти Kernel-Mode
Средство проверки статических драйверов
Обработка проверки ошибок при включении средства проверки драйвера