Анализ аварийного дампа

Не все ошибки можно найти до выпуска, что означает, что не все ошибки, которые вызывают исключения, можно найти до выпуска. К счастью, корпорация Майкрософт включила в пакет SDK для платформы функцию, которая поможет разработчикам собирать сведения об исключениях, обнаруженных пользователями. Функция MiniDumpWriteDumpDump записывает необходимые сведения о аварийном дампе в файл без сохранения всего пространства процесса. Этот файл сведений о аварийном дампе называется мини-dump. В этой технической статье содержатся сведения о том, как писать и использовать мини-dump.

Написание мини-dump

Основные варианты написания мини-dump приведены следующим образом:

  • Никакие действия не выполняются. Windows автоматически создает мини-dump всякий раз, когда программа выдает необработанное исключение. Автоматическое создание мини-dump доступно с Windows XP. Если пользователь разрешает это, мини-dump будет отправлен в Корпорацию Майкрософт, а не разработчику через отчеты об ошибках Windows (WER). Разработчики могут получить доступ к этим мини-приложениям через программу классических приложений Windows.

    Для использования WER требуется:

    • Разработчики могут подписать свои приложения с помощью Authenticode
    • Приложения имеют допустимый ресурс VERSIONINFO в каждом исполняемом файле и библиотеке DLL

    Если вы реализуете настраиваемую подпрограмму для необработанных исключений, настоятельно рекомендуется использовать функцию ReportFault в обработчике исключений, чтобы также отправить автоматизированную мини-передачу в WER. Функция ReportFault обрабатывает все проблемы подключения и отправки мини-dump в WER. Не отправляя мини-дампы в WER, нарушают требования игр для Windows.

    Дополнительные сведения о WER см. в отчеты об ошибках Windows.

  • Используйте продукт из microsoft Visual Studio Team System. В меню отладки нажмите кнопку "Сохранить дамп как", чтобы сохранить копию дампа. Использование локально сохраненного дампа — это только возможность локального тестирования и отладки.

  • Добавьте код в проект. Добавьте функцию MiniDumpWriteDumpDump и соответствующий код обработки исключений для сохранения и отправки мини-dump непосредственно разработчику. В этой статье показано, как реализовать этот параметр. Однако обратите внимание, что MiniDumpWriteDumpDump в настоящее время не работает с управляемым кодом и доступен только в Windows XP, Windows Vista, Windows 7.

Потокобезопасность

MiniDumpWriteDumpDump является частью библиотеки DBGHELP. Эта библиотека не является потокобезопасной, поэтому любая программа, использующая MiniDumpWriteDump, должна синхронизировать все потоки перед попыткой вызова MiniDumpWriteDumpDump.

Написание мини-dump с помощью кода

Фактическая реализация проста. Ниже приведен простой пример использования 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()))
    {
    }
}

В этом примере демонстрируется базовое использование MiniDumpWriteDuriteDumpDump и минимальная информация, необходимая для вызова. Имя файла дампа до разработчика; Однако, чтобы избежать конфликтов имен файлов, рекомендуется создать имя файла из имени и номера версии приложения, идентификаторов процессов и потоков и даты и времени. Это также поможет сохранить мини-dumpы сгруппированы по приложению и версии. Разработчик решает, сколько сведений используется для различения имен файлов minidump.

Следует отметить, что имя пути в предыдущем примере было создано путем вызова функции GetTempPath , чтобы получить путь к каталогу, указанному для временных файлов. Использование этого каталога работает даже с учетными записями пользователей с минимальными привилегиями, а также предотвращает использование мини-dump места на жестком диске после того, как он больше не нужен.

Если вы архивируете продукт во время ежедневного процесса сборки, обязательно включите символы для сборки, чтобы при необходимости можно было выполнить отладку старой версии продукта. Кроме того, необходимо выполнить шаги по поддержанию полной оптимизации компилятора при создании символов. Это можно сделать, открыв свойства проекта в среде разработки и выполнив следующие действия:

  1. В левой части страницы свойств проекта щелкните C/C++. По умолчанию отображается общие параметры. В правой части страницы свойств проекта задайте для параметра "Форматсведений отладки" значение Program Database (/Zi).
  2. В левой части страницы свойства разверните компоновщик и нажмите кнопку "Отладка". В правой части страницы свойства задайте для параметра "Создать отладочную информацию" значение "Да" (/DEBUG).
  3. Нажмите кнопку " Оптимизация" и задайте для ссылок значение Eliminate Unreferenced Data (/OPT:REF).
  4. Установите параметр Enable COMDAT Folding to Remove Redundant COMDATs (/OPT:ICF).

MSDN содержит более подробную информацию о структуре MINIDUMP_EXCEPTION_INFORMATION и функции MiniDumpWriteDumpDump.

Использование Dumpchk.exe

Dumpchk.exe — это программа командной строки, которую можно использовать для проверки правильности создания файла дампа. Если Dumpchk.exe создает ошибку, файл дампа поврежден и не может быть проанализирован. Дополнительные сведения об использовании Dumpchk.exe см. в статье "Использование dumpchk.exe" для проверки файла дампа памяти.

Dumpchk.exe включен на компакт-диск продукта Windows XP и может быть установлен на системный диск\Program Files\Support Tools\ с помощью программы Setup.exe в папке Support\Tools\ на компакт-диске продукта Windows XP. Вы также можете получить последнюю версию Dumpchk.exe, скачайте и установите средства отладки, доступные из средств отладки Windows в Центре разработчика оборудования Windows.

Анализ мини-dump

Открытие мини-dump для анализа так же просто, как создание.

Анализ мини-dump

  1. Откройте Visual Studio.
  2. В меню "Файл" нажмите кнопку "Открыть проект".
  3. Задайте для типа "Файлы дампа", перейдите к файлу дампа, выберите его и нажмите кнопку "Открыть".
  4. Запустите отладчик.

Отладчик создаст имитированный процесс. Имитированный процесс будет остановлен в инструкции, вызвавшей сбой.

Использование общедоступного сервера символов Майкрософт

Чтобы получить стек для сбоев на уровне драйвера или системы, может потребоваться настроить Visual Studio для указания на общедоступный сервер символов Майкрософт.

Установка пути к серверу символов Майкрософт

  1. В меню отладки нажмите кнопку "Параметры".
  2. В диалоговом окне "Параметры" откройте узел отладки и щелкните "Символы".
  3. Убедитесь, что поиск указанных выше расположений выполняется только при загрузке символов вручную , если при отладке не требуется загружать символы вручную.
  4. При использовании символов на удаленном сервере символов можно повысить производительность, указав локальный каталог, в который можно скопировать символы. Для этого введите путь к символам кэша с сервера символов в этот каталог. Чтобы подключиться к общедоступному серверу символов Майкрософт, необходимо включить этот параметр. Обратите внимание, что при отладке программы на удаленном компьютере каталог кэша ссылается на каталог на удаленном компьютере.
  5. Щелкните OK.
  6. Так как вы используете общедоступный сервер символов Майкрософт, появится диалоговое окно лицензионного соглашения конечного пользователя. Нажмите кнопку "Да" , чтобы принять соглашение и скачать символы в локальный кэш.

Отладка minidump с помощью WinDbg

Вы также можете использовать WinDbg, отладчик, который входит в состав средств отладки Windows, для отладки мини-ddump. WinDbg позволяет выполнять отладку без использования Visual Studio. Чтобы скачать средства отладки Windows, см. статью "Средства отладки Windows" в Центре разработчика оборудования Windows.

После установки средств отладки Windows необходимо ввести путь к символам в WinDbg.

Ввод пути символа в WinDbg

  1. В меню "Файл" щелкните "Путь к символам".

  2. В окне пути поиска символов введите следующее:

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

Использование средств защиты копирования с minidumps

Разработчики также должны знать, как их схема защиты копирования может повлиять на мини-dump. Большинство схем защиты копирования имеют собственные средства descramble, и разработчику предстоит узнать, как использовать эти средства с MiniDumpWriteDump.

Итоги

Функция MiniDumpWriteDump Может быть чрезвычайно полезным инструментом для сбора и устранения ошибок после выпуска продукта. Написание пользовательского обработчика исключений, использующего MiniDumpWriteDumpDump , позволяет разработчику настроить сбор сведений и улучшить процесс отладки. Функция достаточно гибкая для использования в любом проекте на основе C++и должна рассматриваться как часть процесса стабильности любого проекта.