try catch __finally
От: Димчанский Литва http://dimchansky.github.io/
Дата: 30.01.04 09:58
Оценка:
Приветствую форум.
Подскажите ка, как лучше сделать. Хотелось что-то типа:
try
{
  // делаем что-то
  ...
  // если плохо, кидаем exception
  if(bad)
  {
     throw Tralialia();
  }
}
finally
{
  // какие-то действия
  finally_proc1();
  finally_proc2();
  finally_proc3();
  // если был exception, то он полетит дальше
}

Понятно, что на c++ finally как бы нету, поэтому самым простым и банальным было бы решить это так:
try
{
  // делаем что-то
  ...
  // если плохо, кидаем exception
  if(bad)
  {
     throw Tralialia();
  }
}
catch(...)
{
  // какие-то действия
  finally_proc1();
  finally_proc2();
  finally_proc3();
  // если был exception, то он полетит дальше
  throw;
}
finally_proc1();
finally_proc2();
finally_proc3();

но это выглядит как-то криво.
И ещё, подскажите тогда, в чём принципиальное различие будет, если использовать __try и __finally? Например, в нашем же случае:
__try
{
  // делаем что-то
  ...
  // если плохо, кидаем exception
  if(bad)
  {
     throw Tralialia();
  }
}
__finally
{
  // какие-то действия
  finally_proc1();
  finally_proc2();
  finally_proc3();
  // если был exception, то он полетит дальше
}

Спасибо за внимание и подсказки.
Re: try catch __finally
От: Denis Россия http://blogs.gotdotnet.ru/personal/Denis
Дата: 30.01.04 10:01
Оценка: 2 (1)
посмотри это:
http://www.rsdn.ru/forum/Message.aspx?mid=517044&only=1
Автор: elich
Дата: 24.01.04
... << RSDN@Home 1.1.0 stable >>
Re: try catch __finally
От: LaptevVV Россия  
Дата: 30.01.04 10:03
Оценка:
Здравствуйте, Димчанский, Вы писали:

Д>Приветствую форум.

И вас приветствую.

Д>И ещё, подскажите тогда, в чём принципиальное различие будет, если использовать __try и __finally? Например, в нашем же случае:

Д>
Д>__try
Д>{
Д>  // делаем что-то
Д>  ...
Д>  // если плохо, кидаем exception
Д>  if(bad)
Д>  {
Д>     throw Tralialia();
Д>  }
Д>}
Д>__finally
Д>{
Д>  // какие-то действия
Д>  finally_proc1();
Д>  finally_proc2();
Д>  finally_proc3();
Д>  // если был exception, то он полетит дальше
Д>}
Д>

Это, как говорят, SEH. А попросту — обработка исключений средствами Windows. Расширение, предоставляеое системами под Windows (Visual — точно, а Борланд — не помню, но вроде тоже). На других платформах работать не будет. Но если перенос некритичен — вполне можно использовать. Подробности можно прочитать у Рихтера.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: try catch __finally
От: Димчанский Литва http://dimchansky.github.io/
Дата: 30.01.04 10:19
Оценка:
Здравствуйте, Denis, Вы писали:

D>посмотри это:

D>http://www.rsdn.ru/forum/Message.aspx?mid=517044&amp;only=1
Автор: elich
Дата: 24.01.04


Спасибо. Гуляя по ссылкам, натолкнулся на такое решение (RAII — Resource Acquisition Is Initialisation):

The following two fragments of code are equivalent:

// 1

try {
     statements1
} catch (...) {
     statements2
     throw;
}
statements2


// 2

struct RAII {
     ~RAII() {
         statements2
     }
};

RAII obj;
statements1


Because the two sections of code have identical effect...

Re[2]: try catch __finally
От: Димчанский Литва http://dimchansky.github.io/
Дата: 30.01.04 10:21
Оценка:
Здравствуйте, LaptevVV, Вы писали:

Д>>И ещё, подскажите тогда, в чём принципиальное различие будет, если использовать __try и __finally? Например, в нашем же случае:

LVV>Это, как говорят, SEH. А попросту — обработка исключений средствами Windows. Расширение, предоставляеое системами под Windows (Visual — точно, а Борланд — не помню, но вроде тоже). На других платформах работать не будет. Но если перенос некритичен — вполне можно использовать. Подробности можно прочитать у Рихтера.

Что-то тут на форуме говорили, что там деструкторы только не вызываются в случае __try и _finally...
Может быть кто-то толково мог бы это объяснить. В чём именно там недостаток?
Re[3]: try catch __finally
От: LaptevVV Россия  
Дата: 30.01.04 10:49
Оценка:
Здравствуйте, Димчанский, Вы писали:

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


Д>Спасибо. Гуляя по ссылкам, натолкнулся на такое решение (RAII — Resource Acquisition Is Initialisation):

Д>

Д>The following two fragments of code are equivalent:

Д>// 1

Д>

try {
Д>     statements1
Д>} catch (...) {
Д>     statements2
Д>     throw;
Д>}
Д>statements2
Д>


Д>// 2

Д>
struct RAII {
Д>     ~RAII() {
Д>         statements2
Д>     }
Д>};

Д>RAII obj;
Д>statements1
Д>


Д>Because the two sections of code have identical effect...

Да, это классическое решение, о котором Страуструп написал в своем талмуде.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: try catch __finally
От: LaptevVV Россия  
Дата: 30.01.04 10:51
Оценка:
Здравствуйте, Димчанский, Вы писали:

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


Д>>>И ещё, подскажите тогда, в чём принципиальное различие будет, если использовать __try и __finally? Например, в нашем же случае:

LVV>>Это, как говорят, SEH. А попросту — обработка исключений средствами Windows. Расширение, предоставляеое системами под Windows (Visual — точно, а Борланд — не помню, но вроде тоже). На других платформах работать не будет. Но если перенос некритичен — вполне можно использовать. Подробности можно прочитать у Рихтера.

Д>Что-то тут на форуме говорили, что там деструкторы только не вызываются в случае __try и _finally...

Д>Может быть кто-то толково мог бы это объяснить. В чём именно там недостаток?
В С++ при возникновении исключения нормально вызываются деструкторы объектов. А в SEH-нет.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: try catch __finally
От: MaximE Великобритания  
Дата: 30.01.04 16:12
Оценка: 4 (1)
Димчанский wrote:

> Подскажите ка, как лучше сделать. Хотелось что-то типа:


Используй scope_guard. Generic&lt;Programming&gt;: Change the Way You Write Exception-Safe Code — Forever

#include <iostream>
#include <boost/bind.hpp>
#include <scope_guard.hpp>

void f(int n)
{
     std::cout << "void f(int n): " << n << '\n';
}

void g(char const* p)
{
     std::cout << "void g(char const* p): " << p << '\n';
}

void h()
{
     std::cout << "void h(): boom\n";
     throw std::logic_error("boom");
}

void j()
{
     g("entered j");
     util::scope_guard g1__(util::make_guard(boost::bind(g, "exiting j")));

     f(1);
     util::scope_guard g2__(util::make_guard(boost::bind(f, 2)));
}

void k()
{
     g("entered k");
     util::scope_guard g1__(util::make_guard(boost::bind(g, "exiting k")));

     f(3);
     util::scope_guard g2__(util::make_guard(boost::bind(f, 4)));

     h();
  }

int main()
{
     try
     {
         j();
         k();
     }
     catch(std::exception&)
     {
     }
}


Вот код самого scope_guard<>:

////////////////////////////////////////////////////////////////////////////////////////////////
// scope_guard.hpp

#pragma once

////////////////////////////////////////////////////////////////////////////////////////////////

namespace util
{

////////////////////////////////////////////////////////////////////////////////////////////////

namespace detail
{

////////////////////////////////////////////////////////////////////////////////////////////////

class scope_guard_base
{
public:
    void dismiss() const
    {
        do_rollback_ = false;
    }

protected:
    scope_guard_base(const scope_guard_base& other)
        :    do_rollback_(other.do_rollback_)
    {
        other.dismiss();
    }

    scope_guard_base()
        :    do_rollback_(true)
    {}

    mutable bool do_rollback_;
};

////////////////////////////////////////////////////////////////////////////////////////////////

template<class F>
class scope_guard_impl : public scope_guard_base
{
public:
    explicit scope_guard_impl(const F& f)
        :    rollback_(f)
    {}

    ~scope_guard_impl()
    {
        if(do_rollback_)
            rollback_();
    }

private:
    F rollback_;
};

////////////////////////////////////////////////////////////////////////////////////////////////

} // namespace detail

////////////////////////////////////////////////////////////////////////////////////////////////

typedef const detail::scope_guard_base& scope_guard;

template<class F>
inline detail::scope_guard_impl<F> make_guard(const F& f)
{
    return detail::scope_guard_impl<F>(f);
}

////////////////////////////////////////////////////////////////////////////////////////////////

} // namespace util

////////////////////////////////////////////////////////////////////////////////////////////////


--
Maxim Egorushkin
MetaCommunications Engineering
http://www.meta-comm.com/engineering/
Posted via RSDN NNTP Server 1.8 beta
Re[2]: try catch __finally
От: Андрей Галюзин Украина  
Дата: 31.01.04 12:36
Оценка:
M> Вот код самого scope_guard<>:

M>
M> class scope_guard_base
M> {
M> public:
M> void dismiss() const
M> {
M> do_rollback_ = false;
M> }

M> protected:
M> scope_guard_base(const scope_guard_base& other)
M> : do_rollback_(other.do_rollback_)
M> {
M> other.dismiss();
M> }

M> scope_guard_base()
M> : do_rollback_(true)
M> {}

M> mutable bool do_rollback_;
M> };

M>


Давно хотел спросить:
А почему бы не использовать uncaught_exception() в качестве do_rollback_ ?

--
aga
Posted via RSDN NNTP Server 1.7 "Bedlam"
Re[3]: try catch __finally
От: Андрей Галюзин Украина  
Дата: 31.01.04 12:45
Оценка:
АГ> А почему бы не использовать uncaught_exception() в качестве do_rollback_ ?

Слишком коротко получилось.
Имелось ввиду для случая, когда ресурсы необходимо освобождать только пр исключении.

--
aga
Posted via RSDN NNTP Server 1.7 "Bedlam"
Re[3]: try catch __finally
От: MaximE Великобритания  
Дата: 31.01.04 19:48
Оценка:
Андрей Галюзин wrote:

[]

> Давно хотел спросить:

> А почему бы не использовать uncaught_exception() в качестве do_rollback_ ?

Во первых, uncaught_exception() не реализован на MS VC++ (независимо от ситуации возвращает одно и тоже значение). Во-вторых, тебе может понадобиться отменить действие вручную.

--
Maxim Egorushkin
MetaCommunications Engineering
http://www.meta-comm.com/engineering/
Posted via RSDN NNTP Server 1.8 beta
Re[4]: try catch __finally
От: Шахтер Интернет  
Дата: 31.01.04 22:48
Оценка: 16 (1)
Здравствуйте, MaximE, Вы писали:

ME>Андрей Галюзин wrote:


ME>[]


>> Давно хотел спросить:

>> А почему бы не использовать uncaught_exception() в качестве do_rollback_ ?

ME>Во первых, uncaught_exception() не реализован на MS VC++ (независимо от ситуации возвращает одно и тоже значение). Во-вторых, тебе может понадобиться отменить действие вручную.


ME>--

ME>Maxim Egorushkin
ME>MetaCommunications Engineering
ME>http://www.meta-comm.com/engineering/


Реализован, только он называется __uncaught_exception() и расположен в заголовке eh.h.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: try catch __finally
От: Вадим Никулин Россия Здесь
Дата: 01.02.04 08:24
Оценка: 1 (1)
Здравствуйте, MaximE, Вы писали:

ME>Во первых, uncaught_exception() не реализован на MS VC++ (независимо от ситуации возвращает одно и тоже значение). Во-вторых, тебе может понадобиться отменить действие вручную.


Это Вы в MSDN'е прочитали? Врут Вам, батенька, врут! Что VC70, что VC71 — все прекрасно исполняют.

   class A
   {
   public:
      A() {}
      ~A() { if( std::uncaught_exception() ) ::MessageBox( 0, "", "", MB_OK ); }
   };
   try
   {
      A a;
      throw 1;
   }
   catch(...)
   {
   }
Re[3]: try catch __finally
От: PM  
Дата: 02.02.04 08:05
Оценка: 2 (1)
Здраствуйте, Андрей Галюзин. Вы писали:

АГ> Давно хотел спросить:

АГ> А почему бы не использовать uncaught_exception() в качестве
АГ> do_rollback_ ?

Может быть, потому что Александреску согласен с Саттером по поводу Item#47 "Uncaught Exceptions" ?
Posted via RSDN NNTP Server 1.7 "Bedlam"
Re[4]: try catch __finally
От: Вадим Никулин Россия Здесь
Дата: 02.02.04 08:51
Оценка:
Здравствуйте, PM, Вы писали:

PM>Здраствуйте, Андрей Галюзин. Вы писали:


АГ>> Давно хотел спросить:

АГ>> А почему бы не использовать uncaught_exception() в качестве
АГ>> do_rollback_ ?

PM>Может быть, потому что Александреску согласен с Саттером по поводу [url=

PM>http://www.gotw.ca/gotw/047.htm
PM>]Item#47 "Uncaught Exceptions"[/url] ?

Да, для try-catch внутри деструкторов uncaught_exception не катит. Однако, таких ситуаций (объектов, требующих commit-or-rollback) внутри деструкторов нужно избегать (имхо).
Re[4]: try catch __finally
От: Андрей Галюзин Украина  
Дата: 02.02.04 13:11
Оценка:
P> Может быть, потому что Александреску согласен с Саттером по поводу [url=
P> http://www.gotw.ca/gotw/047.htm
P> ]Item#47 "Uncaught Exceptions"[/url] ?

Там обсуждается немного другой аспект применения.
На мой взляд, применение unchaught_exception в гуардах вполне кошерно.
Каждый раз писать dismiss несколько утомительно, да и запросто забыть можно.

--
aga
Posted via RSDN NNTP Server 1.7 "Bedlam"
Re[5]: try catch __finally
От: PM  
Дата: 02.02.04 13:35
Оценка:
Здраствуйте, Андрей Галюзин. Вы писали:

P>> Может быть, потому что Александреску согласен с Саттером по поводу

P>> Item#47 "Uncaught<br />
<span class='lineQuote level2'> P&gt;&gt; Exceptions"</span>
?


АГ> Там обсуждается немного другой аспект применения.

АГ> На мой взляд, применение unchaught_exception в гуардах вполне кошерно.
АГ> Каждый раз писать dismiss несколько утомительно, да и запросто забыть
АГ> можно.
Во пример оттуда, ключевая фраза выделена жирным
// Example 19-3: Variant, another wrong solution
//
Transaction::~Transaction()
{
  if( uncaught_exception() ) 
  {
   RollBack();
  }
  else
  {
   // ...       }
}

Again, note that this doesn't do the right thing if a transaction is attempted in a destructor that might be called during stack unwinding:


// Example 19-3(a): Why the variant wrong solution
// is still wrong
//
U::~U() {
  try {
    Transaction t( /*...*/ );
    // do work
  } catch( ... ) {
    // clean up
  }
}
Posted via RSDN NNTP Server 1.7 "Bedlam"
Re[5]: try catch __finally
От: MaximE Великобритания  
Дата: 02.02.04 21:21
Оценка:
Андрей Галюзин wrote:

> На мой взляд, применение unchaught_exception в гуардах вполне кошерно.

> Каждый раз писать dismiss несколько утомительно, да и запросто забыть можно.

Назначение гарда — всегда выполняться, независимо от того, было ли его деструктор вызван при раскрутке стека или при выходе из скопа. Поэтому для него unchaught_exception просто не нужно.

--
Maxim Egorushkin
MetaCommunications Engineering
http://www.meta-comm.com/engineering/
Posted via RSDN NNTP Server 1.8 beta
Re[4]: try catch __finally
От: Шахтер Интернет  
Дата: 04.02.04 04:07
Оценка: 1 (1)
Здравствуйте, MaximE, Вы писали:

ME>Во первых, uncaught_exception() не реализован на MS VC++ (независимо от ситуации возвращает одно и тоже значение). Во-вторых, тебе может понадобиться отменить действие вручную.


Посмотрел сейчас сорцы, в 7.1 исправили этот досадный недочет,

_CRTIMP2 bool __cdecl uncaught_exception()
        {       // report if handling a throw
        return (__uncaught_exception());
        }
_STD_END


__uncaught_exception возвращает true, если есть любое активное SEH исключение, это и раньше было.
... << RSDN@Home 1.1.0 stable >>

Удалено избыточное цитирование. -- ПК.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: try catch __finally
От: MaximE Великобритания  
Дата: 04.02.04 17:07
Оценка:
Шахтер wrote:

> Посмотрел сейчас сорцы, в 7.1 исправили этот досадный недочет,

>
>
> _CRTIMP2 bool __cdecl uncaught_exception()
>         {       // report if handling a throw
>         return (__uncaught_exception());
>         }
> _STD_END
>

>
> __uncaught_exception возвращает true, если есть любое активное SEH исключение, это и раньше было.

Замечательно!

Теперь буду ломать голову, как это добро применить.

--
Maxim Egorushkin
MetaCommunications Engineering
http://www.meta-comm.com/engineering/
Posted via RSDN NNTP Server 1.8 beta
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.