Почему не обрабатывается исключение:
От: a111  
Дата: 24.09.06 12:41
Оценка:
Добрый день!
При трасситовке встроенный отладчик не дает пройти дальше строки записи по нулевому адресу.
При запуске без отладки, приложение закрывается с ошибкой.
Что я сделал не так?
//Visual Studio 2005, дефолтное пустое Win32 приложение.
try
{
    int *i=0;
    *i=2;
}
catch( ... )
{
    MessageBox(0,"Ex","Ex",0);
}
Re: Почему не обрабатывается исключение:
От: Andrei Gorlov  
Дата: 24.09.06 13:04
Оценка:
Проверь ключик Enable C++ Exceptions, должен быть /EHa (with SEH exceptions).
Posted via RSDN NNTP Server 2.0
Re: Почему не обрабатывается исключение:
От: LaptevVV Россия  
Дата: 24.09.06 13:50
Оценка:
Здравствуйте, a111, Вы писали:

A>Добрый день!

A>При трасситовке встроенный отладчик не дает пройти дальше строки записи по нулевому адресу.
A>При запуске без отладки, приложение закрывается с ошибкой.
A>Что я сделал не так?
A>
A>//Visual Studio 2005, дефолтное пустое Win32 приложение.
A>try
A>{
A>    int *i=0;
A>    *i=2;
A>}
A>catch( ... )
A>{
A>    MessageBox(0,"Ex","Ex",0);
A>}

A>

Механизм стандартных исключений в С++ не работает с аварийными исключениями операционнойт системы и компьютера. Для этого нужно использовать SEH (в windows)
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Почему не обрабатывается исключение:
От: Аноним  
Дата: 24.09.06 15:45
Оценка:
Потому что catch ловит то, что было выброшено с помошью throw.
Re: Почему не обрабатывается исключение:
От: Roman Odaisky Украина  
Дата: 24.09.06 16:27
Оценка:
Здравствуйте, a111, Вы писали:

A>Добрый день!

A>При трасситовке встроенный отладчик не дает пройти дальше строки записи по нулевому адресу.
A>При запуске без отладки, приложение закрывается с ошибкой.
A>Что я сделал не так?
A>
A>//Visual Studio 2005, дефолтное пустое Win32 приложение.
A>try
A>{
A>    int *i=0;
A>    *i=2;
A>}
A>catch( ... )
A>{
A>    MessageBox(0,"Ex","Ex",0);
A>}

A>

Потому, что это UB. Компилятор может (1) выкинуть исключение, (2) не выкинуть исключение, (3) отформатировать жесткий диск, (4) не отформатировать жесткий диск... всё, что ему в его пустую голову взбредет.

Если тебе очень-очень-очень хочется обрабатывать такие ситуации, изучай SEH.
До последнего не верил в пирамиду Лебедева.
Re[2]: Почему не обрабатывается исключение:
От: MaximE Великобритания  
Дата: 24.09.06 22:14
Оценка:
Andrei Gorlov wrote:

> Проверь ключик Enable C++ Exceptions, должен быть /EHa (with SEH

> exceptions).

Возможно, не самая лучшая идея. Обсуждалось здесь не раз.

--
Maxim Yegorushkin

No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Posted via RSDN NNTP Server 2.0
Re: Почему не обрабатывается исключение:
От: a111  
Дата: 25.09.06 05:13
Оценка:
ммм понятно
А делфи через SEH работает с исключениями?
Просто там как-то проще. В С++ долго разбирался и то, не до конца разобрался с ними.
Re[2]: Почему не обрабатывается исключение:
От: LuciferMoscow Россия  
Дата: 25.09.06 05:34
Оценка:
Здравствуйте, a111, Вы писали:
A>ммм понятно
A>А делфи через SEH работает с исключениями?
A>Просто там как-то проще. В С++ долго разбирался и то, не до конца разобрался с ними.
Смотри книгу Рихтера. Там в паре глав это подробно расписано.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[2]: Почему не обрабатывается исключение:
От: LaptevVV Россия  
Дата: 25.09.06 06:16
Оценка: 1 (1)
Здравствуйте, a111, Вы писали:

A>ммм понятно

A>А делфи через SEH работает с исключениями?
A>Просто там как-то проще. В С++ долго разбирался и то, не до конца разобрался с ними.
Смотри сюда — первоначальный ликбез

Структурная обработка исключений (SEH) реализована и в Visual C++.NET 2003 и в C++ Builder 6 как расширение стандартного С++. Поддержка SEH обеспечивается операционной системой Windows, поэтому программы, в которых используется SEH, непереносимы. Кроме того, при структурной обработке исключений не выполняется вызов деструкторов — это наиболее важное отличие SEH от стандартного механизма. Поэтому Microsoft не рекомендует смешивать стандартные и структурные исключения в одной программе.
Структурная обработка исключений предоставляет две возможности: обработку исключений try/except и обработку завершения try/finally. Обработка завершения проще, поэтому начнем с нее. В системе Visual C++.NET 2003 синтаксис обработчика завершения выглядит так:

__try { }            // защищенный блок
__finally { }        // блок завершения

Ключевые слова __try и __finally пишутся с двумя подчеркиваниями — обычно в системе Visual C++.NET 2003 так обозначаются все расширения стандартного С++.
Обработчик завершения гарантирует, что блок завершения будет выполнен при любой попытке выхода из защищенного блока — независимо от способа выхода. Выход из __try-блока осуществляется одним из следующих способов:
1. нормальное выполнение всех операторов блока от начала до конца;
2. возникновение исключения во время выполнения операторов блока;
3. выполнение одного из операторов перехода (break, continue, goto, return), хотя этого Джеффри Рихтер [49] рекомендует избегать.
Поведение программы после выполнения финального блока зависит от способа выхода из __try-блока. Если в финальном блоке нет никаких операторов перехода, и он выполняется до конца, то далее в соответствии со способом выхода из защищенного блока:
1. выполняются операторы после финального блока;
2. выполняются операторы после финального блока;
3. выполняется оператор перехода, который вызвал выход из защищенного блока.
Синтаксис обработчика исключений выглядит так:
__try { }            // защищенный блок
__except (фильтр)
{ }
// блок обработки исключения
Обратите внимание, что в SEH после защищенного блока следует единственный обработчик, — либо обработчик завершения, либо обработчик исключения. Несколько обработчиков писать нельзя, и тем более нельзя писать несколько разных обработчиков. Однако разрешается конструкцию try/finally вкладывать в try/except и наоборот, и уровень вложенности не ограничен. Правда, в этом случае существует опасность «запутаться» в порядке выполнения блоков __except и __finally.
При нормальном ходе выполнения программы (когда исключения не возникает) после выполнения операторов защищенного блока блок-обработчик пропускается, и программа продолжает работу со следующего после него оператора. А вот если при выполнении операторов защищенного блока возникло исключение, то обработка его зависит от фильтра. Фильтр — это выражение (в том числе и вызов функции), которое должно принимать одно из трех возможных значений:
    EXCEPTION_CONTINUE_EXECUTION (–1);
    EXCEPTION_CONTINUE_SEARCH (0);
    EXCEPTION_EXECUTE_HANDLER (1);

Очень часто эти константы прописываются в качестве фильтра непосредственно. Только последний вариант означает собственно обработку исключения: выполняются операторы блока обработки, после чего управление передается на первый оператор после него.
Если результат вычисления фильтра равен первой константе, то исключение отклоняется (exception is dismissed). Код в обработчике прерываний никогда не выполняется. Управление возвращается в точку возникновения прерывания и делается попытка снова выполнить ту же инструкцию, которая вызвала исключение.
На первый взгляд поведение не совсем логичное, ведь снова возникнет исключение. Однако не будем забывать, что фильтр – это выражение. Это означает, что на месте фильтра может быть прописано несколько выражений через запятую. В этих выражениях можно исправить причину, вызвавшую исключение. Если необходимо выполнить более сложную работу, то в качестве фильтра может быть прописан вызов функции. Эта функция может получить в качестве параметров любые переменные из защищенного блока, выполнить с ними нужную работу и возвратить константу EXCEPTION_CONTINUE_EXECUTION в качестве результата. Например, если произошло деление на ноль, то функция может изменить значение делителя, и программа сможет «хромать» дальше.
Фильтр EXCEPTION_CONTINUE_SEARCH по своему действию похож на оператор throw без аргумента, то есть «отправляет исключение дальше». Код в обработчике с таким фильтром не выполняется никогда.
Генерация программных исключений выполняется функцией Windows API RaisException(), которую мы рассматривать не будем — подробное изучение SEH в нашу задачу не входит. Однако на одном моменте нужно остановиться. Чем хорошо SEH, так это возможностью «отловить» аппаратные исключения и точно их идентифицировать, естественно, с помощью функции API
DWORD GetExceptCode();
Функция возвращает идентификатор типа исключения, которые определены в файле WinBase.h. Но подключать надо заголовок windows.h. В табл. 4.1 представлены некоторые из этих идентификаторов.

Таблица 4.1. Аппаратные исключения
Значение Описание
EXCEPTION_ACCESS_VIOLATION    //Попытка обратиться к «чужой» памяти
EXCEPTION_FLT_DIVIDE_BY_ZERO    //Деление на ноль дробных чисел
EXCEPTION_FLT_OVERFLOW            //Переполнение для дробных чисел
EXCEPTION_INT_DIVIDE_BY_ZERO    //Деление на ноль для целых чисел
EXCEPTION_INT_OVERFLOW            //Переполнение для целых чисел
EXCEPTION_STACK_OVERFLOW    //Переполнение стека

В составе Windows API реализованы и другие функции, используемые в SEH. Останавливаться подробно мы на этом не будем, так как это не входит в нашу задачу. В справочной системе Visual C++.NET 2003 прописан пример, в котором модифицированы операторы ввода/вывода (листинг 4.22).
//Листинг 4.22. Структурная обработка исключений
// exceptions_try_except_Statement.cpp
// Пример try-except и try-finally 
#include <iostream>
#include <windows.h> // для EXCEPTION_ACCESS_VIOLATION
using std::cout;
using std::endl;
// функция-филтр
int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep) {
   cout<<"in filter."<< endl;
   if (code == EXCEPTION_ACCESS_VIOLATION) {
      cout<<"caught AV as expected."<<endl;
      return EXCEPTION_EXECUTE_HANDLER;            // если авария
   }
   else {
      cout<<"didn't catch AV, unexpected."<< endl;
      return EXCEPTION_CONTINUE_SEARCH;            // если нет аварии
   };
}
int main()
{   int* p = 0x00000000;           // специально-нулевой указатель
   cout<<"hello"<< endl;
   __try{
      cout<<"in try 1"<< endl;
      __try{
         cout<<"in try 2"<< endl;
         *p = 13;                // access violation 
      }__finally{
         cout<<"in finally. termination: "<< endl;
         cout<<(AbnormalTermination() ? "\tabnormal" : "\tnormal")<< endl;
      }
   }__except(filter(GetExceptionCode(), GetExceptionInformation())){
      cout<<"in except"<< endl;
   }
   cout<<"world"<< endl;
}

Программа специально содержит ошибку (нулевой указатель), чтобы показать обработку возникающего исключения по нарушению доступа к памяти (access violation). Демонстрируется также обязательное выполнение финального блока, несмотря на исключение. Программа выводит на экран
hello
in try 1
in try 2
in filter.
caught AV as expected.
in finally. termination:
        abnormal
in except
world

SEH очень подробно описана у Джеффри Рихтера.

Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: Почему не обрабатывается исключение:
От: a111  
Дата: 25.09.06 16:55
Оценка:
Всем спасибо за ответы, пойду читать
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.