Создание минидампа для исключения нарушения прав доступа с помощью SetUnhandledExceptionFilter () - PullRequest
11 голосов
/ 31 января 2011

Я использую следующий код для создания файла мини-дампов всякий раз, когда из моего кода генерируется структурированное исключение:

void CreateMiniDump( EXCEPTION_POINTERS* pep ) 
{
  // Open the file 
typedef BOOL (*PDUMPFN)( 
  HANDLE hProcess, 
  DWORD ProcessId, 
  HANDLE hFile, 
  MINIDUMP_TYPE DumpType, 
  PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, 
  PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, 
  PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);


    HANDLE hFile = CreateFile( _T("C:/temp/MiniDump.dmp"), GENERIC_READ | GENERIC_WRITE, 
    0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); 

    HMODULE h = ::LoadLibrary(L"DbgHelp.dll");
    PDUMPFN pFn = (PDUMPFN)GetProcAddress(h, "MiniDumpWriteDump");

  if( ( hFile != NULL ) && ( hFile != INVALID_HANDLE_VALUE ) ) 
  {
    // Create the minidump 

    MINIDUMP_EXCEPTION_INFORMATION mdei; 

    mdei.ThreadId           = GetCurrentThreadId(); 
    mdei.ExceptionPointers  = pep; 
    mdei.ClientPointers     = TRUE; 

    MINIDUMP_TYPE mdt       = MiniDumpNormal; 

    BOOL rv = (*pFn)( GetCurrentProcess(), GetCurrentProcessId(), 
      hFile, mdt, (pep != 0) ? &mdei : 0, 0, 0 ); 



    // Close the file 

    CloseHandle( hFile ); 

  }

}

LONG WINAPI MyUnhandledExceptionFilter(
 struct _EXCEPTION_POINTERS *ExceptionInfo
)
 {
     CreateMiniDump(ExceptionInfo);
     return EXCEPTION_EXECUTE_HANDLER;
 }

И я делаю SetUnhandledExceptionFilter(MyUnhandledExceptionFilter); из основной точки входа моего приложения (хотя я не устанавливаю его для каждого потока, хотя). После этого, чтобы протестировать этот код, я сделал следующее, чтобы сгенерировать нарушение прав доступа: int* p = 0; *p = 0; Был создан файл дампа. Затем я использовал windbg, открыл файл дампа и использовал команду .ecxr, чтобы получить запись об исключении. Однако никакой информации не поступает (то есть я не получаю стек вызовов). Также, если я использую команду !analyze -v, она может показать строку, где произошел сбой. Кто-нибудь знает, что мне не хватает и как это решить?

Кстати, я использую компилятор VC7 с флагом / EHa (модель исключений асинхронности).

Ответы [ 2 ]

3 голосов
/ 21 декабря 2011

Тем не менее, никакой информации не поступает (т.е. я не получаю стек вызовов)

.ecxr не должен печатать стек вызовов, он просто должен задавать контекст для сохраненной записи исключения - вы хотите сделать что-то вроде k 10, чтобы фактически распечатать его. Или, так как вы используете WinDBG, откройте окно callstack.

(Может быть, вы уже делаете это; я не уверен из вашего описания, как .ecxr терпит неудачу - он должен напечатать что-то, чтобы вы знали, что он / не может сделать ...)

Еще одна вещь, которую нужно проверить, - это то, что вы фактически передаете указатели исключений - код сгенерирует дамп без них, но вы получите фанк-вызов таким образом.

Вы упомянули в комментарии к ответу Алекса с некоторым вмешательством из DLL, перекрывающей ваш фильтр библиотекой времени выполнения ... Это обычная проблема. Мне повезло, используя технику, описанную Олегом Стародумовым :

Существует еще один возможный подход, и его гораздо легче реализовать, чем два предыдущих. После того, как мы зарегистрировали наш собственный фильтр, мы можем исправить начало функции SetUnhandledExceptionFilter, чтобы она больше не могла регистрировать фильтры.

Для этой цели он предоставляет несколько удобных примеров кода, который хорошо мне помогал на протяжении многих лет.

3 голосов
/ 31 января 2011

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

Процесс отладки после смерти с использованием отладчика Visual Studio подробно описан здесь: http://www.codeproject.com/KB/debug/postmortemdebug_standalone1.aspx Для WinDbg используйтеПуть к файлу символов, источника и изображения для предоставления одинаковой информации отладчику.

...