Как написать пример кода, который будет аварийно завершать работу и создавать файл дампа? - PullRequest
16 голосов
/ 17 февраля 2011

я начал изучать windbg и нашел этот хороший пост Как использовать WinDbg для анализа аварийного дампа для приложения VC ++?

Теперь я хочу следовать инструкциям и делать это шаг за шагом. Вот в чем проблема: мне нужно написать пример кода, который может сразу завершиться сбоем, и создать несколько файлов дампа, которые могут использоваться windbg.

Как написать такой код?

void Example4()
{
    int* i = NULL;
    *i = 80;
}

Приведенный выше код сразу завершится сбоем; Тем не менее, я не знаю, где найти файл дампа?

Спасибо

Ответы [ 9 ]

29 голосов
/ 17 февраля 2011
#include <Windows.h>
#include <Dbghelp.h>

void make_minidump(EXCEPTION_POINTERS* e)
{
    auto hDbgHelp = LoadLibraryA("dbghelp");
    if(hDbgHelp == nullptr)
        return;
    auto pMiniDumpWriteDump = (decltype(&MiniDumpWriteDump))GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
    if(pMiniDumpWriteDump == nullptr)
        return;

    char name[MAX_PATH];
    {
        auto nameEnd = name + GetModuleFileNameA(GetModuleHandleA(0), name, MAX_PATH);
        SYSTEMTIME t;
        GetSystemTime(&t);
        wsprintfA(nameEnd - strlen(".exe"),
            "_%4d%02d%02d_%02d%02d%02d.dmp",
            t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
    }

    auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    if(hFile == INVALID_HANDLE_VALUE)
        return;

    MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
    exceptionInfo.ThreadId = GetCurrentThreadId();
    exceptionInfo.ExceptionPointers = e;
    exceptionInfo.ClientPointers = FALSE;

    auto dumped = pMiniDumpWriteDump(
        GetCurrentProcess(),
        GetCurrentProcessId(),
        hFile,
        MINIDUMP_TYPE(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory),
        e ? &exceptionInfo : nullptr,
        nullptr,
        nullptr);

    CloseHandle(hFile);

    return;
}

LONG CALLBACK unhandled_handler(EXCEPTION_POINTERS* e)
{
    make_minidump(e);
    return EXCEPTION_CONTINUE_SEARCH;
}

int main()
{
    SetUnhandledExceptionFilter(unhandled_handler);

    return *(int*)0;
}
4 голосов
/ 17 февраля 2011

Это приведет к исключению разыменования нулевого указателя: *((int*) 0) = 0;

Это приведет к целочисленному делению на ноль: int a = 0; int b = 5 / a;

РЕДАКТИРОВАТЬ: Отладка после приложения сМини-дампы и Visual Studio .NET содержат множество примеров кода и теории использования мини-дампов.

1 голос
/ 24 февраля 2014

Чтобы создать аварийный дамп, я бы не написал необработанный обработчик исключений, предложенный @Abyx по следующим причинам:

a) в случае переполнения буфера или переполнения стекакод, который обрабатывает необработанное исключение, может быть поврежден.В случае OutOfMemoryException, как вы можете загрузить другую библиотеку, такую ​​как DbgHelp.dll?

b) написанный вами код может содержать ошибки.Проверяет ли этот код свободное место на диске перед тем, как записать дамп?Как вы тестируете код, чтобы написать аварийный дамп?У вас есть тестовый модуль для этого?Как ваш модульный тест проверяет правильность дампа?

в) зачем вообще писать код, если Windows может сделать это за вас?

В MSDN есть статья на Сбор дампов пользовательского режима .В основном, есть некоторые настройки реестра, которые вы можете сделать.Преимущество заключается в следующем: Windows создает аварийный дамп операционной системой, а не каким-либо поврежденным кодом в вашем собственном приложении.

1 голос
/ 17 февраля 2011

Файл дампа может быть создан либо программно, либо с помощью средства отладки программных ошибок.В первом случае вы можете использовать функцию MiniDumpWriteDump , а во втором - Dr. Watson (для XP: посмотрите это описание и это очень описательное видео ; для Vista, посмотрите здесь )

1 голос
/ 17 февраля 2011

Автоматическое создание мини-дампов выполняется посмертным отладчиком, поэтому вам нужно начать с него. Самое главное, что это делается отладчиком. Поэтому, если вы просто хотите сгенерировать мини-дамп, вы можете использовать свой обычный отладчик (возможно, visual studio или windbg). Даже диспетчер задач может создавать файлы дампа.

Параметр реестра, который определяет отладчик после смерти: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug

Посмотрите на строку Debugger, и вы будете на пути к поиску мини-дампов.

1 голос
/ 17 февраля 2011

Если вы хотите увидеть аварийный дамп, вам нужно его создать.См. Heisenbug: программа WinApi падает на некоторых компьютерах .Хотя вы можете получить аварийный дамп, предназначенный для отправки в WER, без использования WinQual, он немного запутан (в основном вы можете скопировать его из временного расположения перед его отправкой, точные данные зависят от вашей операционной системы)Я бы порекомендовал создать свой собственный crashdump, используя функции Win API MiniDump.Весь код, необходимый для этого, можно найти по адресу Страница CodeProject, упомянутая в связанном ответе .

0 голосов
/ 09 апреля 2015

В большинстве случаев вы найдете дамп всех приложений в C: \ windows \ minidumps.

Для создания файла дампа вы можете использовать простое решение:

  1. открытый ветер
  2. Файл-> Открыть исполняемый файл
  3. Вы запускаете приложение, которое вылетит
  4. Точка останова сработает
  5. Теперь вы можете использовать .dump в windbg для создания файла dmp

или

  1. Запустите приложение и дождитесь сбоя
  2. Открыть windbg и прикрепить к процессу (Файл-> Присоединить к процессу)
  3. run .dump

Таким образом, вы сможете анализировать этот сбой в любое время:)

0 голосов
/ 30 марта 2012

Я использовал приведенный ниже код при тестировании WinDbg некоторое время назад.

  • Приведенный ниже код работает и генерирует аварийный дамп
  • Есть две функции, так что вы можете видетьтрассировка стека с очевидной цепочкой функций.
  • Чтобы найти дампы сбоев, найдите * .dmp или * .mdmp в C: \ Users
  • Вероятно, лучше, чтобы ОС генерироваласвалка для тебя.Вероятно, именно так будет сгенерировано большинство реальных аварийных дампов, которые вы видите.
  • Код работает, сначала выделяя 1 КБ памяти, затем записывая и ее, и следующие 1 КБ с распознаваемым шестнадцатеричным значением.Обычно он попадает на страницу памяти, помеченную ОС как недоступную для записи, что вызывает сбой.

#include "stdafx.h"
#include "stdio.h"
#include "malloc.h"

void Function2(int * ptr2)
{
    for(int i=0; i < (2 * 1024); i++)
    {
        *ptr2++ = 0xCAFECAFE;
    }
}

void Function1()
{
    int * ptr1 = (int *)malloc(1024 * sizeof(int));

    Function2(ptr1);
}

int _tmain(int argc, _TCHAR* argv[])
{
    printf("Press enter to allocate and corrupt.\r\n");
    getc(stdin);

    printf("Allocating and corrupting...\r\n");
    Function1();

    printf("Done.  Press enter to exit process.\r\n");
    getc(stdin);

    return 0;
}
0 голосов
/ 17 февраля 2011

Попробуйте это:

int main()
{
   int v[5];

   printf("%d", v[10]);
   return 0;
}

или доступ к произвольной ячейке памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...