Re[5]: подход к try-catch
От: Erop Россия  
Дата: 06.10.05 07:50
Оценка:
Здравствуйте, aton, Вы писали:

A>Хм... нет, что бы исправить ситуацию и повторить действие, например кончилось место на диске, получили ексепшн,

A>пользователь подчистил диск, нажал retry, повторили вызов и все заработало


Казалось бы, тогда мы знаем какое исключение ждать и можем не пользоваться в этом месте фильтром, а пользоваться просто catch
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: подход к try-catch
От: Кодт Россия  
Дата: 06.10.05 08:00
Оценка: -1
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>А что вы предлагаете делать для исключений, которые произошли во время обработки исключения?


Заворачиваться в простыню и ползти на кладбище. До тех пор, пока одно исключение не завершено, бросок другого исключения (пусть даже мы его ловим) приведёт к аварийному останову (terminate или abort — надо посмотреть).
Это в случае, если оба исключения возникли в одном потоке и в одном CRT.

В остальных случаях (например, через границу апартаментов, или между С++ной и С-ной функциями, и т.д.) — возможны разные прикольные сочетания, вплоть до возвращения из функции всякого мусора и даже расстрела памяти.
Перекуём баги на фичи!
Re[10]: подход к try-catch
От: Tom Россия http://www.RSDN.ru
Дата: 06.10.05 08:10
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, Tom, Вы писали:


Tom>>Что угодно, но ге гасить его таким образом,

КД>По-подробнее пожалуйста. Писать в файл? Гы. В журнал событий? Возможно, но пусть это делает g_OLE_ErrorExceptionHandler.
Во первых делать обработку так, что бы исключений в обработчике исключений по возможности не возникало, если всё таки они скажем могут возникнуть — то перехватывать именно те, которые могут возникнуть. Вот в твоём примере чего ты "боишься"? Для чего ты пишешь "catch(...)" ?
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re[11]: подход к try-catch
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.10.05 08:28
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>>>Что угодно, но ге гасить его таким образом,

КД>>По-подробнее пожалуйста. Писать в файл? Гы. В журнал событий? Возможно, но пусть это делает g_OLE_ErrorExceptionHandler.
Tom>Во первых делать обработку так, что бы исключений в обработчике исключений по возможности не возникало, если всё таки они скажем могут возникнуть — то перехватывать именно те, которые могут возникнуть. Вот в твоём примере чего ты "боишься"? Для чего ты пишешь "catch(...)" ?

Для отказоустойчивости. Которой много не бывает.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[2]: подход к try-catch
От: ssm Россия  
Дата: 06.10.05 08:31
Оценка: :)
Здравствуйте, 0xDEADBEEF, Вы писали:

DEA>Используем "фильтр исключений" (вот так):


Re[12]: подход к try-catch
От: Tom Россия http://www.RSDN.ru
Дата: 06.10.05 08:32
Оценка: +1
КД>Для отказоустойчивости. Которой много не бывает.
catch(...) не добавляет отказоустойчивости, а наабарот. Поясню, допустим ты залез в обработчике эксепшина куда то далеко в память и напакостил там, а потом вылеьел по AV, AV сглотнётся и о том, что произошло ты никогда не узнаешь, а потом будешь долго чесать репу почему в совершенно другом куске кода программа спотыкается на ровном месте
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re[9]: подход к try-catch
От: _Winnie Россия C++.freerun
Дата: 06.10.05 08:36
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>>А что вы предлагаете делать для исключений, которые произошли во время обработки исключения?


К>ех пор, пока одно исключение не завершено, бросок другого исключения (пусть даже мы его ловим) приведёт к аварийному останову

???


int main()
{
    try
    {
        throw 0;
    }
    catch(...)
    {
        try
        {
            throw 0;
        }
        catch(...)
        {
            printf("hello!\n");
        }
    }
}
Правильно работающая программа — просто частный случай Undefined Behavior
Re[13]: подход к try-catch
От: _Winnie Россия C++.freerun
Дата: 06.10.05 08:40
Оценка: +1
Здравствуйте, Tom, Вы писали:

КД>>Для отказоустойчивости. Которой много не бывает.

Tom>catch(...) не добавляет отказоустойчивости, а наабарот. Поясню, допустим ты залез в обработчике эксепшина куда то далеко в память и напакостил там, а потом вылеьел по AV, AV сглотнётся и о том, что произошло ты никогда не узнаешь, а потом будешь долго чесать репу почему в совершенно другом куске кода программа спотыкается на ровном месте

А причем тут AV? Мы вроде как про С++ исключения говорим? Если вылетело SEH исключение, то тут уже игра по другим правилам. Лично я просто делаю делаю попытку save, записываю crash-dump и умираю.

А как ты предлагаешь выкидывать исключения из DLL, которая может использоватьсся даже в другом языке, ничего не знающем про исключения? Тут можно только E_FAIL верунть.
Правильно работающая программа — просто частный случай Undefined Behavior
Re[10]: подход к try-catch
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.10.05 08:48
Оценка:
Здравствуйте, _Winnie, Вы писали:

КД>>>А что вы предлагаете делать для исключений, которые произошли во время обработки исключения?


К>>ех пор, пока одно исключение не завершено, бросок другого исключения (пусть даже мы его ловим) приведёт к аварийному останову

_W>???

[/ccode]
_W>catch(...)
_W>{
_W> printf("hello!\n");
_W>}
[/ccode]

Тогда уж лучше сразу предложить пользователю абмнормалиться по паре стопариков
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[14]: подход к try-catch
От: Tom Россия http://www.RSDN.ru
Дата: 06.10.05 08:54
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Здравствуйте, Tom, Вы писали:


КД>>>Для отказоустойчивости. Которой много не бывает.

Tom>>catch(...) не добавляет отказоустойчивости, а наабарот. Поясню, допустим ты залез в обработчике эксепшина куда то далеко в память и напакостил там, а потом вылеьел по AV, AV сглотнётся и о том, что произошло ты никогда не узнаешь, а потом будешь долго чесать репу почему в совершенно другом куске кода программа спотыкается на ровном месте

_W>А причем тут AV? Мы вроде как про С++ исключения говорим? Если вылетело SEH исключение, то тут уже игра по другим правилам. Лично я просто делаю делаю попытку save, записываю crash-dump и умираю.


Уговорил Напакостил в памяти и вылетело не AV а что то типа std::range_error, от этого не легче
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re[10]: подход к try-catch
От: Кодт Россия  
Дата: 06.10.05 09:30
Оценка:
Хм. Да, пожалуй, наврал. Интересно, почему такой сдвиг в башке?..
А, сообразил!

Облом происходит, если второе исключение кинуто при размотке стека, т.е. из деструктора.
Перекуём баги на фичи!
Все новое украдено до нас! :)))
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.11.05 13:15
Оценка: 71 (4) :))
Здравствуйте, 0xDEADBEEF, Вы писали:

DEA>Используем "фильтр исключений" (вот так):

DEA>
DEA>void ExceptionFilter()
DEA>{
DEA>    try {
DEA>        throw;
DEA>    } catch(Exception1 const& e) {
DEA>        //делаем одно
DEA>    } catch(Exception2 const& e) {
DEA>        //делаем второе
DEA>    } catch(Exception3 const& e) {
DEA>        //делаем третье
DEA>    } catch(Exception4 const& e) {
DEA>        //делаем четвертое
DEA>    } catch(Exception5 const& e) {
DEA>        //делаем пятое
DEA>    } catch(...) {
DEA>        //делаем еще что-то
DEA>    }
DEA>}
DEA>


Перечитывая в очередной раз "Язык программирования C++" 3-е издание нашел этот трюк у Страуструпа!
Причем он там его чуть по другому показывает ($14.6.3.1, $14.6.3.2).

Была, значиться функция
void g() throw(Yerr);

и захотели ее использовать там, где кроме Yerr еще и другие ошибки выскакивают. Что же делать, чтобы std::unexpected() не вызывался? А вот чего:
class STC{ // store and reset class
    unexpected_handler old;
public:
    STC(unexpected_handler f) { old = set_unexpected(f) ; }
    ~STC() { set_unexpected(old) ; }
};

это вроде RAII для установки unexpected_handler. Затем делается новое исключение, производное от Yerr:
class Yunexpected : public Yerr {};

void throwY() throw(Yunexpected) { throw Yunexpected(); }

и предоставляется обертка вокруг g():
void networked_g() throw(Yerr)
{
    STC xx( &throwY ); // Теперь unexpected() генерирует Yunexpected.
    g();
}


Только вот проблема, не известно, что за исключение было порождено. Тогда приведенный выше код модифицируется:
class Yunexpected : public Yerr {
public :
    Network_exception * pe;
    Yunexpected(Network_exception * p) : pe( p ? p->clone() : 0 ) {}
    ~Yunexpected() { delete pe; }
}

void throwY() throw(Yunexpected)
{
    try {
        throw; // Сгенерировать заново, чтобы немедлено перехватить!
    }
    catch( Network_exception & p ) {
        throw Yunexpected(&p); // Сгенерировать отображенное исключение.
    }
    catch( ... ) {
        throw Yunexpected(0);
    }
}



Знакомый до боли принцип в последнем варианте throwY(), не правда ли

А еще недавно тема всплывала, где книгу Страуструпа ругали, мол попса, все поверхносно и написано не понятно. А классиков, оказывается, перечитывать полезно
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Все новое украдено до нас! :)))
От: Pavel Chikulaev Россия  
Дата: 25.11.05 13:30
Оценка: :)
Здравствуйте, eao197, Вы писали:

[snipped]
Супер!
+1

E>А еще недавно тема всплывала, где книгу Страуструпа ругали, мол попса, все поверхносно и написано не понятно. А классиков, оказывается, перечитывать полезно

Сегодня же начну Кстати там и expression templates есть...
Re[2]: Все новое украдено до нас! :)))
От: srggal Украина  
Дата: 25.11.05 14:26
Оценка:
Здравствуйте, Pavel Chikulaev, Вы писали:

E>>А еще недавно тема всплывала, где книгу Страуструпа ругали, мол попса, все поверхносно и написано не понятно. А классиков, оказывается, перечитывать полезно

PC>Сегодня же начну Кстати там и expression templates есть...

Там много чего, есть, но eao197, как всегда передергивает

Большинство нарицаний было в сторону перевода книги
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[3]: Все новое украдено до нас! :)))
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.11.05 17:21
Оценка:
Здравствуйте, srggal, Вы писали:

E>>>А еще недавно тема всплывала, где книгу Страуструпа ругали, мол попса, все поверхносно и написано не понятно. А классиков, оказывается, перечитывать полезно

PC>>Сегодня же начну Кстати там и expression templates есть...

S>Там много чего, есть, но eao197, как всегда передергивает


Да куда уж мне передергивать
Re[2]: Язык программирования C++ (специальное издание)
Автор: LaptevVV
Дата: 11.11.03

Re[3]: Язык программирования C++ (специальное издание)
Автор: Lorenzo_LAMAS
Дата: 11.11.03
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[2]: подход к try-catch
От: remark Россия http://www.1024cores.net/
Дата: 25.11.05 17:32
Оценка:
Здравствуйте, 0xDEADBEEF, Вы писали:

DEA>Hello, Аноним !

DEA>You wrote on Wed, 05 Oct 2005 10:44:31 GMT:

А>> Каким образом можно избавиться от повторяющихся catch

А>> блоков, желательно без использования макросов?
DEA>Используем "фильтр исключений" (вот так):


Неужели про это знали только мы с тобой вдвоём

Пара идей, которые, у меня созрели:


DEA>ЗЫ. Естественно, фильтров и их вариаций может быть много...



Практика показывает, что чем меньше, тем лучше.
Если это, например, COM-компонент, то я делаю один фильтр исключений на все методы COM-компонента. Это как нельзя лучше структурирует всё политику обработки исключений в приложении.
Если гуёвое приложение, то я использую 2 — один при выполнении гуёвых команд по действию пользователя, второй для действий, выполняемых в рабочих потоках.


Пару интересных идей по этой теме есть здесь. Хотя, конечно, если пишешь на С++, то самому это всё реализовывать засадно. Хотя в простом варианте реализовать можно.

Например, так:

void exceptionHandler()
{
    ExceptionManager::getHandler().run();
}



Можно применять, например, при работе приложения в нескольких режимах — когда можно показывать мессаджбоксы, и когда нельзя. Или при изменении каких-либо других подсистем приложения, например, провайдера БД.


В крупных проектах, где не обойтись без логирования и мониторинга приложения, я стандартно применяю следующий приём:


void _exceptionHandler(const std::string& sFunctionName)
{
    LOG << "Exception: " << sFunctionName;
    // Реальная обработка исключения
}


#define exceptionHandler() _exceptionHandler(__FUNCTION__)



При жестоком желании не дублировать код (какое у меня обычно бывает ) можно структурно обрабатывать иерархии исключений:


Допустим, есть такая иерархия исключений:

struct A1 {};
struct B1 : A1 {};
struct C1 : A1 {};
struct A2 {};
struct B2 : A2 {};
struct C2 : B2 {};



Её можно обрабатывать следующим обработчиком:


void exceptionHandler()
{
    try
    {
        throw;
    }
    catch (const A1&)
    {
        try
        {
            throw;
        }
        catch (const B1&)
        {
            handlingForB1();
        }
        catch (const C1&)
        {
            handlingForC1();
        }
        handlingForA1();
    }
    catch (const A2&)
    {
        try
        {
            throw;
        }
        catch (const B2&)
        {
            try
            {
                throw;
            }
            catch (const C2&)
            {
                handlingForC2();
            }
            handlingForB2();
        }
        handlingForA2();
    }
    handlingForAllErrors();
};



... Хотя, конечно, это для маньяков



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: подход к try-catch
От: Dobre  
Дата: 08.12.05 14:54
Оценка:
Здравствуйте, 0xDEADBEEF, Вы писали:

DEA>Hello, Аноним !

DEA>You wrote on Wed, 05 Oct 2005 10:44:31 GMT:

А>> Каким образом можно избавиться от повторяющихся catch

А>> блоков, желательно без использования макросов?
DEA>Используем "фильтр исключений" (вот так):
DEA>
DEA>void TheFunction()
DEA>{
DEA>    try {
DEA>        //твоя функция
DEA>    } catch(...) {
DEA>        ExceptionFilter();
DEA>    }
DEA>}

DEA>void ExceptionFilter()
DEA>{
DEA>    try {
DEA>        throw;
DEA>    } catch(Exception1 const& e) {
DEA>        //делаем одно
DEA>    } catch(Exception2 const& e) {
DEA>        //делаем второе
DEA>    } catch(Exception3 const& e) {
DEA>        //делаем третье
DEA>    } catch(Exception4 const& e) {
DEA>        //делаем четвертое
DEA>    } catch(Exception5 const& e) {
DEA>        //делаем пятое
DEA>    } catch(...) {
DEA>        //делаем еще что-то
DEA>    }
DEA>}
DEA>


DEA>ЗЫ. Естественно, фильтров и их вариаций может быть много...



Приветствую.

Вот пытаюсь Ваш чудо способ применить у себя, но заметил одну небольшую непонятную ситуацию у себя. Может Вы проясните мне, как действовать в данной ситуации. Такое ощущение, что деструктор класса-исключения будет кидаться несколько раз:

void TheFunction()
{
    try 
    {
        // предположим у нас тут зовется что-то вроде
        ....
        throw Exception1();
    }
    catch(...) 
    {
        ExceptionFilter();
    }                             // ВОТ ТУТ ВЫЗОВЕТСЯ ДЕСТРУКТОР ВТОРОЙ РАЗ

}

void ExceptionFilter()
{
    try 
    {
        throw;
    } 
    catch(Exception1 const& e) 
    {
        //делаем одно
    }                             // ВОТ ТУТ ВЫЗОВЕТСЯ ДЕСТРУКТОР ПЕРВЫЙ РАЗ
    catch(Exception2 const& e) 
    {
        //делаем второе
    } 
    catch(Exception3 const& e) 
    {
        //делаем третье
    } 
    catch(Exception4 const& e) 
    {
        //делаем четвертое
    } 
    catch(Exception5 const& e) 
    {
        //делаем пятое
    } 
    catch(...) 
    {
        //делаем еще что-то
    }
}



А вот теперь представим, что я пытаюсь отловить exception который определен в какой то сторонней библиотеке. И определен так, что как только мы ему зовем деструктор второй раз, так он тотчаз стреляет мой программе прямо в висок (что если у него в деструкторе стоит: delete pSomePtr

Как жить ? Как быть ? Или может я что то не так сделал ?
Re[3]: подход к try-catch
От: Dobre  
Дата: 08.12.05 16:01
Оценка:
Лююююди, человеки!!!
Спасайте !
Re[3]: подход к try-catch
От: Кодт Россия  
Дата: 08.12.05 22:38
Оценка:
Здравствуйте, Dobre, Вы писали:

<>

Это баг компилятора VC6, VC7. VC7.1 полёт нормальный.
http://www.rsdn.ru/Forum/?mid=412976
Автор: LMars
Дата: 17.10.03
Перекуём баги на фичи!
Re[2]: подход к try-catch
От: AndrewJD США  
Дата: 17.05.06 13:25
Оценка:
Здравствуйте, 0xDEADBEEF, Вы писали:

DEA>
DEA>void ExceptionFilter()
DEA>{
DEA>    try {
DEA>        throw;
DEA>    } catch(Exception1 const& e) {
DEA>        //делаем одно
DEA>    } catch(Exception2 const& e) {
DEA>        //делаем второе
DEA>    } catch(Exception3 const& e) {
DEA>        //делаем третье
DEA>    } catch(Exception4 const& e) {
DEA>        //делаем четвертое
DEA>    } catch(Exception5 const& e) {
DEA>        //делаем пятое
DEA>    } catch(...) {
DEA>        //делаем еще что-то
DEA>    }
DEA>}

DEA>Используем "фильтр исключений" (вот так):
DEA>void TheFunction()
DEA>{
DEA>    try {
DEA>        //твоя функция
DEA>    } catch(...) {
DEA>        ExceptionFilter();
            throw; // << Заново выбросить
DEA>    }
DEA>}
DEA>


Небольшой вопросик.
Сколько раз, согласно стандарту, мы можем перевыбрасывать одно и то же исключение? Т.е. первый раз мы перевыбросили исключение в фильтре. Насколько законно его еще раз выбросить?
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.