Как я получаю строковое описание катастрофического отказа Win32, в то время как в фильтре Верхнего уровня (я ищу адрес инструкции наверху стека),

Если я использую класс/метод как тот, описал здесь, как я могу получить описание/адрес вызова наверху стека?

В основном я хочу некоторое значение, которое я могу использовать в вызове для нашей системы отслеживания ошибок. Я хочу "исключительно" определить на основе адреса инструкции, которая вызвала исключение.

(Это обычно - что-то вроде формы mydll.dll! 1234ABDC ())

Править:

Некоторая справочная информация:

Я создаю мини-дамп на адрес электронной почты к дефектной системе слежения (fogbugz). Для сокращения дубликатов, я пытаюсь придумать разумную "подпись" для катастрофического отказа. Я знаю, что существует xml PI для FB, но он требует пользовательского входа в систему, и мы еще не уверены, что можем позволить себе иметь людей, осуществляющих сниффинг нашего трафика и получающих пользовательскую информацию. Пользование электронной почтой также более просто на данный момент реализовать. Позже мы будем использовать API XML для представления мини-дампов.

6
задан Tim 2 March 2010 в 21:22
поделиться

4 ответа

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

try 
{
  // whatever
}
except (MyExceptionFilter(GetExceptionInformation()))
{
}

Ваш фильтр будет выглядеть примерно так

LONG WINAPI MyExceptionFilter (
   EXCEPTION_POINTERS * pExcept,
   BOOL                 fPassOn)
{
   EXCEPTION_RECORD * pER = pExcept->ExceptionRecord;
   DWORD dwExceptionCode = pER->ExceptionCode;

   TCHAR szOut[MAX_PATH*4]; // exception output goes here.
   szOut[0] = 0;

   MEMORY_BASIC_INFORMATION mbi;
   DWORD cb = VirtualQuery (pER->ExceptionAddress, &mbi, sizeof(mbi));
   if (cb == sizeof(mbi))
      {
      TCHAR szModule[MAX_PATH];
      if (GetModuleFileName ((HMODULE)mbi.AllocationBase, szModule, MAX_PATH))
         {
         wsprintf(szOut, "Exception at '%s' + 0x%X", szModule, 
                  (ULONG_PTR)pER->ExceptionAddress - (ULONG_PTR)mbi.AllocationBase);
         }
      }

   return EXCEPTION_EXECUTE_HANDLER;
}

Конечно, вам нужно будет немного настроить вывод для 64-битных архитектур, поскольку ExceptionAddress и AllocationBase в этом случае будут 64-битными величинами.

4
ответ дан 17 December 2019 в 02:27
поделиться

GetExceptionInformation вернет структуру EXCEPTION_POINTERS, которая содержит информацию об исключении. Член ExceptionRecord содержит член ExceptionAddress, который является адресом исключения.

Вам нужно будет сопоставить этот адрес с относительным расположением модуля в вашем коде, чтобы он был полезен. Вы можете использовать GetModuleHandleEx с GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, чтобы получить HMODULE (который также является базовым адресом модуля). Затем GetModuleInformation может использоваться для получения фактического имени модуля, в котором возникла исключительная ситуация.

Это может быть не очень полезно для вас, если ошибка действительно находится внутри системной DLL. Более сложной схемой было бы создание трассировки стека (с использованием Stackwalk64 в dbghelp) и игнорирование самых верхних кадров, которых нет в вашем коде.

1
ответ дан 17 December 2019 в 02:27
поделиться

Вы можете избежать мучений с печатью строки для исключения (что произойдет, если вы можете сохранить минидамп, но не можете отформатировать строку без сбоя?), сохранив вместо этого минидамп и используя cdb.exe или windbg.exe для извлечения информации об исключении.

0
ответ дан 17 December 2019 в 02:27
поделиться

Структура EXCEPTION_POINTERS , которая отправляется на TopLevelFilter () , содержит структуру EXCEPTION_RECORD , которая содержит ExceptionAddress . По какому именно этому адресу вы можете выяснить, в какой библиотеке DLL нарушает код операции, перечислив модули с помощью CreateToolhelp32Snapshot . Вы также можете использовать функции из dbghelp.dll , чтобы найти символ, соответствующий адресу (функции, в которой он находится)

1
ответ дан 17 December 2019 в 02:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: