Преобразовать std::exception в EXCEPTION_POINTERS

У меня может быть полное недопонимание, как использовать API Google Breakpad, и я открыт для комментариев / предложений / грубых замечаний, если это так. Я пытаюсь вызвать следующую функцию C++:

bool WriteMinidumpForException(EXCEPTION_POINTERS* exinfo);

У меня есть ссылка на std::exception:

try {
  return QApplication::notify(receiver, event);
} catch (std::exception &ex) {
  eh_.WriteMinidumpForException(?????);
  // ... do some more stuff and ultimately kill this process
}

(eh_ это google_breakpad::ExceptionHandler.)

Что я положил в ?????

Предыстория: Причина, по которой это необходимо (я думаю), заключается в том, что Qt не будет поддерживать исключение, генерируемое в обработчике событий. Он не будет распространяться правильно, и, следовательно, созданный Breakpad мини-дамп совершенно бесполезен, потому что фактический контекст исключения был потерян. Вместо этого вы должны перехватить все исключения и обработать их в переопределении QApplication::notify()Это то, что я пытаюсь сделать. В случае исключения я хочу немедленно написать свой мини-дамп для этого исключения (что звучит как WriteMinidumpForException будет делать), а затем уведомить пользователя и выйти из приложения. Но я не уверен, что передать как EXCEPTION_POINTERS* параметр.

2 ответа

Решение

В компиляторе MSVC исключения C++ добавляются в собственную систему исключений Windows (SEH, Структурная обработка исключений). Однако существует довольно большое несоответствие импеданса, концепция фильтра исключений не очень подходит для C++. К тому времени, когда обработчик перехвата ловит исключение, исключение SEH уже обработано, и стек разматывается. Информация EXCEPTION_POINTERS -gonzo. Фильтры исключений действительно существуют, именно так они фильтруют определенный тип, который вы хотите перехватить, однако они автоматически генерируются компилятором. Нет разумного синтаксиса C++, чтобы сделать их полезными.

Вам нужно углубиться в поддержку компилятора для обработки исключений SEH. Использовать __try, __except ключевые слова (__finally необязательно), и ваш фильтр перехватывает код исключения для исключения C++, 0xe04d5343 ('MSC'). Однако вы теряете возможность отлавливать определенный тип исключений C++, так как сантехника скрыта в CRT без источника. Поместите C++ попробуйте внутри __try чтобы исправить это так, ваш __except видит только исключения, которые код C++ не фильтровал.

Использование SetUnhandledExceptionFilter() является еще одним способом сделать это, кстати, вы действительно должны рассматривать его как конечную поддержку любого необработанного исключения, независимо от расположения кода. Это лучший способ создать мини-дамп аварийного приложения. И последнее, но не менее важное: создание мини-дампа аварийного приложения внутри самого процесса - не лучший подход. Есть много шансов, что это не будет работать хорошо, состояние процесса может быть сильно повреждено. Один из режимов сбоя - блокировка кучи процесса. Не исключено, что повреждение кучи является очень распространенной причиной аварии. Исправьте это с помощью "процесса защиты", используйте именованное событие, чтобы подать сигнал на создание минидампа. Вашему фильтру исключений нужно только установить событие, которое всегда работает.

Исключения в Windows SEH и C++ никоим образом не переплетаются - простой способ решить эту проблему - использовать собственную __try __except, например, разыменование нулевого указателя.

Что-то вроде:

__try {
  * (int *) 0 = 0;
} 
__except 
    (
        eh_.WriteMinidumpForException(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER
    ) 
{
}
Другие вопросы по тегам