Analyse de vidage sur plantage

Tous les bugs ne peuvent pas être découverts avant la publication, ce qui signifie que tous les bugs qui lancent des exceptions ne peuvent pas être trouvés avant la publication. Heureusement, Microsoft a inclus dans le SDK Platform une fonction pour aider les développeurs à collecter des informations sur les exceptions découvertes par les utilisateurs. La fonction MiniDumpWriteDump écrit les informations nécessaires de vidage de crash dans un fichier sans sauvegarder tout l’espace de processus. Ce fichier d’informations de vidage de crash est appelé un minidump. Cet article technique fournit des informations sur la façon d’écrire et d’utiliser un minidump.

Écriture d’un minidump

Les options de base pour écrire un minidump sont les suivantes :

  • Ne rien faire. Windows génère automatiquement un minidump chaque fois qu’un programme lance une exception non gérée. La génération automatique d’un minidump est disponible depuis Windows XP. Si l’utilisateur le permet, le minidump sera envoyé à Microsoft, et non au développeur, via le Windows Error Reporting (WER). Les développeurs peuvent accéder à ces minidumps via le Programme d’application pour ordinateur de bureau Windows.

    L’utilisation du WER nécessite :

    • Les développeurs doivent signer leurs applications en utilisant Authenticode.
    • Les applications doivent avoir une ressource VERSIONINFO valide dans chaque exécutable et DLL.

    Si vous implémentez une routine personnalisée pour les exceptions non gérées, il est fortement recommandé d’utiliser la fonction ReportFault dans le gestionnaire d’exceptions pour également envoyer un minidump automatisé au WER. La fonction ReportFault gère toutes les questions de connexion et d’envoi du minidump au WER. Ne pas envoyer les minidumps au WER viole les exigences des Jeux pour Windows.

    Pour plus d’informations sur le WER, veuillez consulter la section Rapport d’erreurs Windows.

  • Utilisez un produit du Microsoft Visual Studio Team System. Dans le menu Déboguer, cliquez sur Enregistrer le vidage sous pour enregistrer une copie d’un vidage. L’utilisation d’un vidage enregistré localement n’est qu’une option pour les tests et le débogage internes.

  • Ajoutez du code à votre projet. Ajoutez la fonction MiniDumpWriteDump et le code de gestion des exceptions approprié pour enregistrer et envoyer un minidump directement au développeur. Cet article démontre comment implémenter cette option. Cependant, notez que MiniDumpWriteDump ne fonctionne pas actuellement avec le code géré et n’est disponible que sur Windows XP, Windows Vista, Windows 7.

Sécurité des threads

MiniDumpWriteDump fait partie de la bibliothèque DBGHELP. Cette bibliothèque n’est pas thread-safe, donc tout programme utilisant MiniDumpWriteDump doit synchroniser tous les threads avant de tenter d’appeler MiniDumpWriteDump.

Écriture d’un minidump avec du code

L’implémentation réelle est simple. Voici un exemple simple de l’utilisation de MiniDumpWriteDump.

#include <dbghelp.h>
#include <shellapi.h>
#include <shlobj.h>

int GenerateDump(EXCEPTION_POINTERS* pExceptionPointers)
{
    BOOL bMiniDumpSuccessful;
    WCHAR szPath[MAX_PATH]; 
    WCHAR szFileName[MAX_PATH]; 
    WCHAR* szAppName = L"AppName";
    WCHAR* szVersion = L"v1.0";
    DWORD dwBufferSize = MAX_PATH;
    HANDLE hDumpFile;
    SYSTEMTIME stLocalTime;
    MINIDUMP_EXCEPTION_INFORMATION ExpParam;

    GetLocalTime( &stLocalTime );
    GetTempPath( dwBufferSize, szPath );

    StringCchPrintf( szFileName, MAX_PATH, L"%s%s", szPath, szAppName );
    CreateDirectory( szFileName, NULL );

    StringCchPrintf( szFileName, MAX_PATH, L"%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", 
               szPath, szAppName, szVersion, 
               stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, 
               stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, 
               GetCurrentProcessId(), GetCurrentThreadId());
    hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, 
                FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);

    ExpParam.ThreadId = GetCurrentThreadId();
    ExpParam.ExceptionPointers = pExceptionPointers;
    ExpParam.ClientPointers = TRUE;

    bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), 
                    hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL);

    return EXCEPTION_EXECUTE_HANDLER;
}


void SomeFunction()
{
    __try
    {
        int *pBadPtr = NULL;
        *pBadPtr = 0;
    }
    __except(GenerateDump(GetExceptionInformation()))
    {
    }
}

Cet exemple démontre l’utilisation basique de MiniDumpWriteDump et les informations minimales nécessaires pour l’appeler. Le nom du fichier de vidage est laissé au choix du développeur ; cependant, pour éviter les collisions de noms de fichiers, il est conseillé de générer le nom de fichier à partir du nom et du numéro de version de l’application, des IDs de processus et de thread, et de la date et de l’heure. Cela aidera également à garder les minidumps groupés par application et version. Il appartient au développeur de décider de la quantité d’informations utilisée pour différencier les noms de fichiers de minidump.

Il convient de noter que le chemin d’accès dans l’exemple précédent a été généré en appelant la fonction GetTempPath pour récupérer le chemin du répertoire désigné pour les fichiers temporaires. L’utilisation de ce répertoire fonctionne même avec des comptes d’utilisateurs aux privilèges les plus limités, et cela empêche également le minidump d’occuper de l’espace sur le disque dur une fois qu’il n’est plus nécessaire.

Si vous archivez le produit pendant votre processus de build quotidien, assurez-vous également d’inclure les symboles pour la build afin de pouvoir déboguer une ancienne version du produit, si nécessaire. Vous devez également prendre des mesures pour maintenir les optimisations complètes du compilateur tout en générant des symboles. Cela peut être fait en ouvrant les propriétés de votre projet dans l’environnement de développement et, pour la configuration de publication, en procédant comme suit :

  1. Sur le côté gauche de la page de propriétés du projet, cliquez sur C/C++. Par défaut, cela affiche les paramètres Généraux. Sur le côté droit de la page de propriétés du projet, définissez Format des Informations de Débogage sur Base de Données de Programme (/Zi).
  2. Sur le côté gauche de la page de propriétés, développez Linker, puis cliquez sur Débogage. Sur le côté droit de la page de propriétés, définissez Générer des infos de débogage sur Oui (/DEBUG).
  3. Cliquez sur Optimisation, et définissez Références sur Eliminer les données non référencées (/OPT:REF).
  4. Définissez Activer le regroupement COMDAT sur Supprimer les COMDAT redondants (/OPT:ICF).

Pour plus d’informations, veuillez consulter la structure MINIDUMP_EXCEPTION_INFORMATION et la fonction MiniDumpWriteDump.

Utilisation de Dumpchk.exe

Dumpchk.exe est un utilitaire en ligne de commande qui peut être utilisé pour vérifier qu’un fichier de vidage a été créé correctement. Si Dumpchk.exe génère une erreur, le fichier de vidage est alors corrompu et ne peut pas être analysé. Pour des informations sur l’utilisation de Dumpchk.exe, veuillez consulter Comment utiliser Dumpchk.exe pour vérifier un fichier de vidage mémoire.

Dumpchk.exe est inclus sur le CD produit de Windows XP et peut être installé sur System Drive\Program Files\Support Tools\ en exécutant Setup.exe dans le dossier Support\Tools\ sur le CD produit de Windows XP. Vous pouvez également obtenir la dernière version de Dumpchk.exe en téléchargeant et en installant les outils de débogage disponibles depuis Outils de débogage Windows sur Windows Hardware Developer Central.

Analyse d’un minidump

Ouvrir un minidump pour l’analyse est aussi facile que d’en créer un.

Pour analyser un minidump

  1. Ouvrez Visual Studio.
  2. Dans le menu Fichier, cliquez sur Ouvrir le projet.
  3. Définissez Type de fichiers sur Fichiers de vidage, naviguez jusqu’au fichier de vidage, sélectionnez-le et cliquez sur Ouvrir.
  4. Exécutez le débogueur.

Le débogueur créera un processus simulé. Le processus simulé sera arrêté à l’instruction qui a causé le crash.

Utilisation du serveur de symboles publics Microsoft

Pour obtenir la pile des crashes au niveau du pilote ou du système, il pourrait être nécessaire de configurer Visual Studio pour pointer vers le serveur de symboles public de Microsoft.

Pour définir un chemin vers le serveur de symboles Microsoft

  1. Dans le menu Déboguer, cliquez sur Options.
  2. Dans la boîte de dialogue Options, ouvrez le nœud Débogage, et cliquez sur Symboles.
  3. Assurez-vous que Rechercher les emplacements ci-dessus uniquement lorsque les symboles sont chargés manuellement n’est pas sélectionné, sauf si vous souhaitez charger les symboles manuellement lors de votre débogage.
  4. Si vous utilisez des symboles sur un serveur de symboles distant, vous pouvez améliorer les performances en spécifiant un répertoire local vers lequel les symboles peuvent être copiés. Pour ce faire, entrez un chemin pour Mettre en cache les symboles du serveur de symboles dans ce répertoire. Pour vous connecter au serveur de symboles public de Microsoft, vous devez activer ce paramètre. Notez que si vous déboguez un programme sur un ordinateur distant, le répertoire de cache fait référence à un répertoire sur l’ordinateur distant.
  5. Cliquez sur OK.
  6. Parce que vous utilisez le serveur de symboles public de Microsoft, une boîte de dialogue d’Accord de Licence Utilisateur Final apparaît. Cliquez sur Oui pour accepter l’accord et télécharger les symboles dans votre cache local.

Débogage d’un minidump avec WinDbg

Vous pouvez également utiliser WinDbg, un débogueur qui fait partie des Outils de Débogage Windows, pour déboguer un minidump. WinDbg vous permet de déboguer sans avoir à utiliser Visual Studio. Pour télécharger les Outils de Débogage Windows, veuillez consulter Outils de débogage Windows sur Windows Hardware Developer Central.

Après avoir installé les Outils de Débogage Windows, vous devez entrer le chemin des symboles dans WinDbg.

Pour entrer un chemin de symbole dans WinDbg

  1. Dans le menu Fichier, cliquez sur Chemin des Symboles.

  2. Dans la fenêtre Chemin de recherche des symboles, saisissez ceci :

    "srv\*c:\\cache\*https://msdl.microsoft.com/download/symbols;"

Utilisation des outils de protection de copie avec des minidumps

Les développeurs doivent également être conscients de la façon dont leur schéma de protection contre la copie pourrait affecter le minidump. La plupart des schémas de protection contre la copie ont leurs propres outils de décryptage, et il appartient au développeur d’apprendre à utiliser ces outils avec MiniDumpWriteDump.

Résumé

La fonction MiniDumpWriteDump peut être un outil extrêmement utile pour collecter et résoudre les bugs après que le produit a été publié. Écrire un gestionnaire d’exceptions personnalisé qui utilise MiniDumpWriteDump permet au développeur de personnaliser la collecte d’informations et d’améliorer le processus de débogage. La fonction est suffisamment flexible pour être utilisée dans n’importe quel projet basé sur C++ et devrait être considérée comme faisant partie de tout processus de stabilité de projet.