Utilisation du débogueur de noyau pour rechercher une fuite de mémoire Kernel-Mode
Le débogueur de noyau détermine l’emplacement précis d’une fuite de mémoire en mode noyau.
Activer l’étiquetage de pool
Vous devez d’abord utiliser GFlags pour activer le balisage de pool. GFlags est inclus dans Outils de débogage pour Windows. Démarrez GFlags, choisissez l’onglet Registre système, case activée la zone Activer le balisage de pool, puis sélectionnez Appliquer. Vous devez redémarrer Windows pour que ce paramètre prenne effet.
Sur Windows Server 2003 et versions ultérieures de Windows, le balisage de pool est toujours activé.
Détermination de la balise de pool de la fuite
Pour déterminer la balise de pool associée à la fuite, il est généralement plus simple d’utiliser l’outil PoolMon pour cette étape. Pour plus d’informations, consultez Utilisation de PoolMon pour rechercher Kernel-Mode fuites de mémoire.
Vous pouvez également utiliser le débogueur de noyau pour rechercher des balises associées à des allocations de pool volumineuses. Pour ce faire, procédez comme suit :
Rechargez tous les modules à l’aide de la commande .reload (Recharger le module).
Utilisez l’extension !poolused . Incluez l’indicateur « 4 » pour trier la sortie par mémoire paginée en utilisant :
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
Déterminez la balise de pool associée à la meilleure utilisation de la mémoire. Dans cet exemple, le pilote qui utilise la balise « Abc » utilise le plus de mémoire, soit près de 34 Mo. Par conséquent, la fuite de mémoire se trouve probablement dans ce pilote.
Recherche de la fuite
Une fois que vous avez déterminé la balise de pool associée à la fuite, suivez cette procédure pour localiser la fuite elle-même :
Utilisez la commande ed (Enter Values) pour modifier la valeur de la variable système globale PoolHitTag. Cette variable globale entraîne l’arrêt du débogueur chaque fois qu’une balise de pool correspondant à sa valeur est utilisée.
Définissez PoolHitTag sur la balise que vous pensez être la source de la fuite de mémoire. Le nom du module « nt » doit être spécifié pour accélérer la résolution des symboles. La valeur de la balise doit être entrée au format little endian (c’est-à-dire en arrière). Étant donné que les balises de pool sont toujours quatre caractères, cette balise est en fait A-b-c-space, pas simplement A-b-c. Utilisez donc la commande suivante :
kd> ed nt!poolhittag ' cbA'
Pour vérifier la valeur actuelle de PoolHitTag, utilisez la commande db (Mémoire d’affichage) :
kd> db nt!poolhittag L4 820f2ba4 41 62 63 20 Abc
Le débogueur s’interrompt chaque fois que le pool est alloué ou libéré avec la balise Abc. Chaque fois que le débogueur s’interrompt sur l’une de ces allocations ou opérations gratuites, utilisez la commande kb (Display Stack Backtrace) du débogueur pour afficher la trace de pile.
À l’aide de cette procédure, vous pouvez déterminer quel code résident dans la mémoire surallouer le pool avec la balise Abc.
Pour effacer le point d’arrêt, définissez PoolHitTag sur zéro :
kd> ed nt!poolhittag 0
S’il existe plusieurs emplacements différents où la mémoire avec cette balise est allouée et qu’ils se trouvent dans une application ou un pilote que vous avez écrit, vous pouvez modifier votre code source pour utiliser des balises uniques pour chacune de ces allocations.
Si vous ne pouvez pas recompiler le programme, mais que vous souhaitez déterminer l’un des emplacements possibles du code à l’origine de la fuite, vous pouvez désassembler le code à chaque emplacement et utiliser le débogueur pour modifier ce code résidant en mémoire afin que chaque instance utilise une balise de pool distincte (et précédemment inutilisée). Laissez ensuite le système s’exécuter pendant plusieurs minutes ou plus. Après un certain temps, arrêtez à nouveau avec le débogueur et utilisez l’extension !poolfind pour rechercher toutes les allocations de pool associées à chacune des nouvelles balises.