Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Переброска исключений по цепочке.  (Прочитано 19201 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« : 27-04-2010 10:02 » 

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

Код:
void method()
{
  try
  {
    lock();
    // some actions...
    unlock();
  }
  catch (Exception &e)
  {
    unlock(); // исключения ловим из-за него

    // теперь надо передать пойманное исключение дальше, не изменяя его.
  }
}

Как можно бросить исключение дальше, не создавая нового объекта?
Условие такое: Exception - базовый класс для исключений.


Дополнение: у меня BCB6. Особенность VCL-классов в том, что они исключительно динамически создаваемые и VCL-исключения обрабатываются только по ссылке.
Нашел таки в доке пример:

Код:
catch (Exception &e)
{
  // обработка
  throw; // переброска
}
« Последнее редактирование: 27-04-2010 10:13 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 27-04-2010 10:11 » 

вроде бы так

-дезинформация удалена )) -
« Последнее редактирование: 27-04-2010 10:44 от Алексей1153++ » Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 27-04-2010 10:15 » 

Леш, я так пробовал. К моменту броска объект по ссылке умирает и дальше летит гарантированный segmentaion fault.

Дополнил первый пост примером, как Борланд предлагают перебрасывать.


А method() throw(....) вообще здесь не причем Улыбаюсь Це только декларация и никаких действий не предписано.
« Последнее редактирование: 27-04-2010 10:17 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 27-04-2010 10:18 » 

ага, нашёл, кажись

мсдн говорит

Цитата
A throw-expression with no operand re-throws the exception currently being handled. Such an expression should appear only in a catch handler or in a function called from within a catch handler. The re-thrown exception object is the original exception object (not a copy). For example:


try
 {
   throw CSomeOtherException();
}
catch(...) {  // Handle all exceptions
   // Respond (perhaps only partially) to exception
   throw;       // Pass exception to some other handler
}
 
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #4 : 27-04-2010 10:39 » 

Не, Ром, всё правильно. Именно throw; жаль я раньше тему не видел. Но последние минут 10 к российским ресурсам (многим во всяком случае) не было доступа. На форум не мог зайти. Куча линков не открывалась. Ща вроде работает.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 27-04-2010 10:42 » 

Успокоили Улыбаюсь А то мало ли чего Борланд напридумывал...
Под рукой только борландовская дока. Страуструп дома на диване отдыхает, а лезть в MSDN по пустякам - много времени потерять.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #6 : 27-04-2010 11:21 » 

Offtopic:
Код:
void method()
{
  try
  {
    lock();
    // some actions...
    unlock();
  }
  catch (Exception &e)
  {
    unlock(); // исключения ловим из-за него

    // теперь надо передать пойманное исключение дальше, не изменяя его.
  }
}
код плох тем, что тебе приходится выполнять работу по чистке данных
я бы использовал RAII


а по теме уже всё сказано Улыбаюсь
Записан

Странно всё это....
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 27-04-2010 12:12 » 

Цитата: LogRus
я бы использовал RAII
Если систематически, то имеет смысл завести некий SyncObject с lock в конструкторе и unlock в деструкторе. Но бывают одноразовые случаи, когда так делать - только неоправданно усложнять.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 27-04-2010 12:58 » 

Как раз и используется критическая секция в некоторых методах в объекте.

Другой случай: SQL-запрос с переменными подстановки и Commit в try и Rollback и DeleteVariables в catch. Но в таком случае я ошибки на месте обрабатываю и дальше уже кидаю что-то осмысленное.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
sss
Специалист

ru
Offline Offline

« Ответ #9 : 28-04-2010 00:48 » new

RXL, действительно, если передавать статический объект исключения, он будет очищен при выходе из зоны видимости
1) в CBuilder да! Зона видимости кончается пределами той функции, в которой объявлено исключение.
2) в VC  - не понятно! Нет! Когда происходит (и происходит ли) очистка не помню (не знаю).
В своё время очень много пришлось переделывать - я протаскиваю свою библиотеку кодов, так, что бы  она одинаково работала как в BCB, так и в VC.

Поэтому, если надо передавать объект исключения,  я использую динамические объекты исключений ( с подсчетом ссылок).
Код:
void some1(void) throw (ESystemError*)
{
  try
  {
    throw new __ESystemError( ::GetLastError());
  }
  catch(...)
  {
    ...
    throw;
  }

void main(void)
{
   try
  {
    some1();
  }
  catch( EExcept* e)
  {
    SHOWTHROW( e);
    e->Release();
  }
}
Записан

while (8==8)
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #10 : 28-04-2010 03:22 » 

...........только неоправданно усложнять.

это иллюзия Улыбаюсь надо написать 3 строчки кода убрав при этом 3 другие, вопрос в чём сложность?

Как раз и используется критическая секция в некоторых методах в объекте.
Эммм, не понял к чему это..

Другой случай: SQL-запрос с переменными подстановки и Commit в try и Rollback и DeleteVariables в catch. Но в таком случае я ошибки на месте обрабатываю и дальше уже кидаю что-то осмысленное.
Ну это отдельный случай, т.к. оракл использует C интрфейс (в стандартной OCI) и там нет исключений. Но ты же наверняка уже написал свою обёртку на CPP вокруг OCI Улыбаюсь

RXL, действительно, если передавать статический объект исключения, он будет очищен при выходе из зоны видимости
1) в CBuilder да! Зона видимости кончается пределами той функции, в которой объявлено исключение.
2) в VC  - не понятно! Нет! Когда происходит (и происходит ли) очистка не помню (не знаю).

что нам говорит стандарт:
Цитата
The memory for the exception object is allocated in an unspecified way, except as noted in 3.7.4.1. If a
handler exits by rethrowing, control is passed to another handler for the same exception. The exception
object is destroyed after either the last remaining active handler for the exception exits by any means other
than rethrowing, or the last object of type std::exception_ptr (18.8.5) that refers to the exception object is
destroyed, whichever is later. In the former case, the destruction occurs when the handler exits, immediately
after the destruction of the object declared in the exception-declaration in the handler, if any. In the latter
case, the destruction occurs before the destructor of std::exception_ptr returns. The implementation
may then deallocate the memory for the exception object; any such deallocation is done in an unspecified
way.

Я работаю с VC++ 2003 и GCC, и всегда выбрасываю исключения так
Код:
throw Expetion(params);
и ловлю на зависимо от того, как далеко обработчик исключения (в стеке вызовов, рядом с точкой выброса или на 20 функции вверх)
Код:
catch(const Exception & e)
проблем с обработкой исключений не разу не наблюдал


Записан

Странно всё это....
sss
Специалист

ru
Offline Offline

« Ответ #11 : 28-04-2010 04:04 » 

LogRus, вот вот... Я тоже проблем не наблюдал, пока тот же самый код не перенес в CBuilder. Там маленько сложнее. Если не изменяет память, в момент регенерации исключения, сам объект исключения повторно копируется в новый экземпляр (используя копирующий конструктор).
Записан

while (8==8)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #12 : 28-04-2010 06:07 » 

Как раз и используется критическая секция в некоторых методах в объекте.
Эммм, не понял к чему это..

Я использую блокировку в некоторых методах - критическую секцию - и из-за нее и задумался о перехвате исключений и последующей передачи из дальше.

Цитата
Другой случай: SQL-запрос с переменными подстановки и Commit в try и Rollback и DeleteVariables в catch. Но в таком случае я ошибки на месте обрабатываю и дальше уже кидаю что-то осмысленное.
Ну это отдельный случай, т.к. оракл использует C интрфейс (в стандартной OCI) и там нет исключений. Но ты же наверняка уже написал свою обёртку на CPP вокруг OCI Улыбаюсь

Использую VCL-компоненты Oracle DAO для BCB - там уже все объектное, хотя большой разницы с процедурным подходом не видно - только исключения вносят разнообразие. Обертку я тоже написал, но уже поверх DAO, для уменьшения телодвижений, повышения надежности и с более удобным управлением пулом сессий.

LogRus, вот вот... Я тоже проблем не наблюдал, пока тот же самый код не перенес в CBuilder. Там маленько сложнее. Если не изменяет память, в момент регенерации исключения, сам объект исключения повторно копируется в новый экземпляр (используя копирующий конструктор).

Можно проверить, сделав свой класс исключения и подсчитать количество созданных объектов.
« Последнее редактирование: 28-04-2010 06:10 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #13 : 28-04-2010 06:15 » 

Я использую блокировку в некоторых методах - критическую секцию - и из-за нее и задумался о перехвате исключений и последующей передачи из дальше.

Если ты отлов исключения используешь для снятия блокировки и с последующим перевыбросом исключения, то правильней использовать RAII, например, реализация boost::mutex использует критическую секцию, как базовый примитив и RAII для установки и снятия блокировок
Записан

Странно всё это....
sss
Специалист

ru
Offline Offline

« Ответ #14 : 28-04-2010 06:51 » 

Гм, LogRus а если
Код:
catch(const Exception & e)
заменить на
Код:
catch(Exception & e)

Проблем то же не будет?

В любом случае, я для себя уже давно выработал свой стиль использования исключений и не жалею...
Записан

while (8==8)
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #15 : 28-04-2010 08:12 » 

в принципе проблем не будет, это просто доп.защита от случайного вызова не константного метода
Записан

Странно всё это....
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 28-04-2010 18:26 » 

LogRus, boost в моем случае исключен - слишком старый компилятор, да к тому же еще и Борланд. Только стандартные средства. Потом, руками оно легче контролируется, чем автоматом.

Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #17 : 29-04-2010 03:56 » 

RXL, это отмазки Улыбаюсь boost прекрасно собирается для Borland
Я не настаиваю, просто привожу примеры использования RAII

ведь смотри как красиво Улыбаюсь
Код:

typedef boost::mutex mutex; // или другой boost::mutex или tbb::mutex
                                               // благо семантика одинаковая

mutex m;
void foo()
{
  mutex::scoped_lock l(m); // Lock
  ..............................
} // Unlock


void foo2()
{
  ........................................
  if ()
  {
     mutex::scoped_lock l(m); // Lock
     ........................
  } // Unlock
  ..............................
}


« Последнее редактирование: 29-04-2010 04:00 от LogRus » Записан

Странно всё это....
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #18 : 29-04-2010 09:00 » 

Цитата: LogRus
надо написать 3 строчки кода убрав при этом 3 другие, вопрос в чём сложность?
В умножении сущностей без необходимости - бритва Оккама не позволяет Улыбаюсь Я это расцениваю как преждевременную оптимизацию. Вынос имеет смысл только при неоднократном использовании. В противном случае, чем проще - тем лучше. Обоснуй обратное.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines