Передача ошибок обработчика сообщений Win32

Цикл foreach в Java использует базовый механизм итератора. Таким образом, это идентично следующему:

Iterator<String> iterator = someList.iterator();

while (iterator.hasNext()) {
  String item = iterator.next();
  System.out.println(item);
}
6
задан 23 July 2009 в 00:40
поделиться

4 ответа

Я бы не стал регистрировать пользовательские сообщения Window для обработки ошибок. Я имею в виду, что этот подход будет работать нормально, но в этом нет необходимости.

Между прочим, ваш обработчик catch, указанный выше, должен улавливать все 3 исключения. Ваша процедура диалога выполняется в том же потоке, который вызывает CreateDialog. Создание немодального диалога не порождается рабочим потоком. Немодальный диалог по-прежнему получает сообщения через цикл GetMessage / Translate / Dispatch. Там есть стековый фрейм, что означает, что когда вы бросаете, он должен полностью раскручиваться до вашего WinMain блока try / catch.

Разве это не то поведение, которое вы?

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

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

Подход 1. Используйте OutputDebugString ().
Это хорошо, потому что только тот, у кого есть отладчик, действительно заметит то, что на самом деле не должно выходить из строя. Очевидно, что у тех, кто пытается использовать обработку исключений, есть много минусов

Подход 2. Используйте MessageBox.
Это не намного лучше, чем подход 1, однако он позволяет не разработчикам видеть ошибку.

Подход 3. Используйте регистратор ошибок.
Вместо того, чтобы использовать 'throw', чтобы потом тебя поймали, а затем 'занести в журнал', вы можете добавить ведение журнала во время сбоя и использовать стандартные коды возврата Win32 для выхода из приложения:

if(msg == WM_INITDIALOG) //Or some other message
{
    /*
        Load some critical resource(s) here. For instnace:

        const HANDLE someResource = LoadImage(...);

        if(someResource == NULL)
        {
                  LogError("Cannot find resource 'foo');
        }
    */

    return TRUE;
}
1
ответ дан 10 December 2019 в 02:51
поделиться

Обратные вызовы AFAIK WinAPI (например, процедуры окна / диалога / потока) не должны распространять исключения. Это связано с тем, что внутреннее устройство WinAPI (которое вызывает обратный вызов) не подготовлено для обработки исключений. Они не могут быть подготовлены, потому что реализация исключений зависит от компилятора, в то время как код в WinAPI DLL фиксирован, поэтому он не может обрабатывать все возможные реализации распространения исключений.

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

Дополнительный уровень сложности добавляется незнанием источника обратного вызова (в общем - для некоторых сообщений это можно вывести). Сообщения, обрабатываемые вашей процедурой диалога, проходят цикл сообщений тогда и только тогда, когда они были отправлены в ваш диалог. Если они были отправлены, они пропускают цикл и выполняются напрямую. Кроме того, если сообщение отправлено, вы не знаете, кто отправляет сообщение - это вы? А может винда? Или какое-то другое окно в другом процессе пытается что-то сделать? (Однако это было бы рискованно.) Вы не знаете, подготовлен ли вызывающий сайт к исключению.

Некоторый способ обходного решения предлагает Boost.Exception . Библиотека позволяет как-то сохранить пойманное исключение и использовать его (в частности, повторно выбросить). Таким образом, вы можете заключить свою диалоговую процедуру в throw {... } catch (...) {...} где в catch вы захватываете исключение и сохраняете его для последующего использования.

РЕДАКТИРОВАТЬ: Начиная с C ++ 11 функции Boost.Exception для хранения объекта исключения являются частью STD. Для этого вы можете использовать std :: exception_ptr .

Однако некоторые проблемы все еще остаются. Вам все равно нужно как-то восстановить и вернуть какое-то значение (для сообщений, требующих возврата). И вам нужно будет решить, что делать с сохраненным исключением. Как получить к нему доступ? Кто это сделает? Что он будет с этим делать?

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

8
ответ дан 10 December 2019 в 02:51
поделиться
Другие вопросы по тегам:

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