информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
За кого нас держат?Страшный баг в WindowsГде водятся OGRы
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
 Умер Никлаус Вирт 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Достаточно часто для функции можно быть уверенным близко к... 07.03.09 00:27  Число просмотров: 2605
Автор: Heller <Heller> Статус: Elderman
<"чистая" ссылка>
> А при чем здесь память? Вообще то эксепшоны должны
> выкидываться в ответ на любую непредвиденную ситуацию
> (собственно эксепшон). Будь то access denied при открытии
> файла или невалидные данные от юзера. bad_alloc - на самом
> деле одно из самых редких исключений.
Достаточно часто для функции можно быть уверенным близко к 100%, что она не кидает никаких эксепшенов. В том-то и дело, что bad_alloc - это тот самый эксепшен, который часто даже почти в тривиальной функции теоретически может возникнуть. Ну, допустим написал я функцию, которая внутри где-то у себя ресайзит вектор. И это единственное место где она может упать. Могу ли я писать throw() в декларации? Все же bad_alloc - штука крайне редкая, и в 99.99% приложений вообще никогда не встретится.

> Зато можно спасти бэдаллоком, который ГАРАНТИРОВАННО можно
> бросить (в смысле стандарт требует, чтобы места под
> объект-исключение bad_alloc хватало ВСЕГДА, даже когда на
> все остальное памяти уже нет). И да, по unexpected ситуацию
> вообще не спасешь - можно только сделать дамп памяти для
> дебага или что то в том же духе. Независимо от того,
> сколько у тебя памяти
Я может быть слишком халатен, но мой подход таков: "Нет памяти, значит покупай железо". Память находится вне компетенции девелопера. На bad_alloc я просто плевал. Никак его не обрабатываю (кроме сообщения "купи памяти"), и даже не пытаюсь спасти рантайм. Пусть упадет хоть как - не мое дело. Но в то же время не смотря на мою халатность писать для функции throw(), если она работает с памятью, как-то уж даже для меня - слишком. Но с другой стороны почему бы и нет? Вот и колеблюсь.

> Ситуация не невозможная, а исключительная - разные вещи.
> Исключительные ситуации вполне ожидаемы.
Допустим я реализую что-то с указателями ("умные" не всегда подходят) - такое случается, бывает. И вот я отладил уже на 100% какую-нибудь функцию и уверен вообще совсем и полностью, что бага нет. Имею я право писать throw()? Или все же то что я уверен еще не значит, что я имею право на throw()? Таки и assert-ы бывает срабатывают.

> Аппаратные исключения кэтчатся не всегда: не всеми
> компиляторами и не при любых настройках (насколько я помню
> стандарт вообще ничего не говорит о том, как с ними
> работать). В VC есть два способа: поставить se_translator
> или catch(...) с асинхронными исключениями (/EHa)
Ну да, я главным образом о Винде говорю.


> > 99% всего что пишешь. Мне конечно не сложно, но однако
> ж.
> Да
Кстати, есть еще и чисто психологически момент: когда смотришь на объявление функции что-нибудь типа
ret_type getSomeStuff();
то ты спокоен. Когда же смотришь на объявление вроде такого:
ret_type getSomeStuff() throw(...);
то уже подходешь к функции более серьезно. Ну а если еще и конкретные эксепшены указаны - то вообще обработаешь каждый в отдельности с гораздо большей вероятностью, чем при "голом" объявлении.

> Ты ЧИВО? Эксепшоны ВООБЩЕ не предназначены для отлавливания
> неправильной работы с указателями (для этого есть умные
> указатели). Независимо от этого экспепшены сами по себе -
> КРАЙНЕ полезная фича плюсов, а вот спецификации этих самых
> исключений не используются практически нигде (кроме разве
> что спецификации throw() )
Немного не так выразился. Но однако повторюсь, что нет-нет, да обычные опасные указатели все же приходится использовать. Добавь сюда работу со старыми библиотеками (никуда не денешься) и сопровождение старого кода. Под никсами можно обрабатывать сигналы, а под виндой единственственный вариант, какой я вижу - эксепшены. Указатели и аллокации я привел потому что это самые трудно контролируемые ошибки, которые сразу же приводят к падению, если грамотно их не обработать. С остальными ошибками все же как-то проще, согласись.

Кстати, еще одно преимущество использования throw() - дополнительные компиляторные оптимизации, которые могут быть произведены.
<programming>
[C++] Декларации throw - есть ли смысл? 06.03.09 14:46  
Автор: Heller <Heller> Статус: Elderman
<"чистая" ссылка>
Вычитал недавно где-то рекомендацию использовать декларации throw "на всякий случай". Ранее я о них просто не знал, поэтому не юзал, а тут начал применять. Речь идет о таких объявлениях:
bool empty() throw();

Я вот начал их использовать, но по-правде говоря не вижу большого в них смысла. Какое ваше мнение на этот счет? Стоит ли по каждому поводу лепить throw(...)? Очень многие функции работают с динамической памятью и эксепшены могут теоретически вылетать очень запросто. С другой стороны если памяти перестало хватать - ситуацию уже вряд ли спасешь эксепшенами, и можно вывалиться в unexpected(). Или другая ситуация: функция не должна выкидывать эксепшены, но теоретически где-то у нее внутри есть операции с указателями, и в качестве "невозможной ситуации" вполне может вылететь эксепшн при использовании, например, нулевого указателя.

То есть получается, что с одной стороны, если честно объявлять как throw(...) все функции, которые умеют чисто физически выкидывать эксепшены, то приедется так объявлять 99% всего что пишешь. Мне конечно не сложно, но однако ж. Если же игнорить потенциальные ошибки с указателями и динамической памятью - теряется вообще смысл в эксепшенах и потенуиальные падения системы, которые даже толком потом и не отловишь.

В общем, я в замешательстве. Что скажете?
[C++] Update: Может подвести итого по рузультатам обуждения: Декларации throw - есть ли смысл? 09.03.09 00:33  
Автор: void <Grebnev Valery> Статус: Elderman
Отредактировано 10.03.09 03:08  Количество правок: 1
<"чистая" ссылка>
1) не использовать спецификации exception (типа throw(A,B, ...,))
2) не использовать throw() в функциях, которые предполагается inline
3) не использовать throw() для виртуальных функций
4) использовать throw() (за исключением 2,3) для оптимицации кода Microsoft компилятором + для анализатора кода (для VC++ 9.0).

Как думаете?
==============
Сегодня ещё пообсуждали с девелоперами на работе. Вывод такой - не использовать вообще спецификации екзепшон.
Согласен (включая UPD) 10.03.09 10:23  
Автор: Heller <Heller> Статус: Elderman
<"чистая" ссылка>
Компилеро зависимо. В принципе, это хинт оптимизирующему... 07.03.09 05:50  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
> Вычитал недавно где-то рекомендацию использовать декларации
> throw "на всякий случай". Ранее я о них просто не знал,
> поэтому не юзал, а тут начал применять. Речь идет о таких
> объявлениях:
> bool empty() throw();

Компилеро зависимо. В принципе, это хинт оптимизирующему компилеру. В MSDN всё написано

Про throw()
C++ Language Reference
Exception Handling: Default Synchronous Exception Model
With the new synchronous exception model, now the default, exceptions can be thrown only with a throw statement. Therefore, the compiler can assume that exceptions happen only at a throw statement or at a function call. This model allows the compiler to eliminate the mechanics of tracking the lifetime of certain unwindable objects, and to significantly reduce the code size, if the objects' lifetimes do not overlap a function call or a throw statement. The two exception handling models, synchronous and asynchronous, are fully compatible and can be mixed in the same application.

Про не nothow() и также про __declspec(nothrow)

This attribute tells the compiler that the declared function and the functions it calls never throw an exception. With the synchronous exception handling model, now the default, the compiler can eliminate the mechanics of tracking the lifetime of certain unwindable objects in such a function, and significantly reduce the code size.

По своему опыту я наблюдал в одном бенчмарке (моём) прирост производительности ~20-50% после удаления в некоторых местах throw()


> Я вот начал их использовать, но по-правде говоря не вижу
> большого в них смысла. Какое ваше мнение на этот счет?

К сожалению смысл начинается и кончается на полиси компании для которой ты работаешь. А так ..., если сам себе хозяин - 100% использовать обработку экзепшн в C++ (если С++ код сам и будешь использовать). Если не только сам будешь использовать - это другая история.

> Стоит ли по каждому поводу лепить throw(...)? Очень многие
> функции работают с динамической памятью и эксепшены могут
> теоретически вылетать очень запросто.

Без язвительности - если с памятью вылетают экзепшны, то надо что-то делать кроме как думать про экзепшн.

> памяти перестало хватать - ситуацию уже вряд ли спасешь
> эксепшенами, и можно вывалиться в unexpected().

Согласен.

> Или другая
> ситуация: функция не должна выкидывать эксепшены, но
> теоретически где-то у нее внутри есть операции с
> указателями, и в качестве "невозможной ситуации" вполне
> может вылететь эксепшн при использовании, например,
> нулевого указателя.
>
> То есть получается, что с одной стороны, если честно
> объявлять как throw(...) все функции, которые умеют чисто
> физически выкидывать эксепшены, то приедется так объявлять
> 99% всего что пишешь. Мне конечно не сложно, но однако ж.
> Если же игнорить потенциальные ошибки с указателями и
> динамической памятью - теряется вообще смысл в эксепшенах и
> потенуиальные падения системы, которые даже толком потом и
> не отловишь.

Про ето я написал выше. Это просто хинт компилеру. Не более того.
Ни фига не хинт. Компилер должен сгенерировать код, который... 07.03.09 07:42  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Компилеро зависимо. В принципе, это хинт оптимизирующему
> компилеру. В MSDN всё написано

> Про ето я написал выше. Это просто хинт компилеру. Не более
> того.

Ни фига не хинт. Компилер должен сгенерировать код, который ОБЯЗАН дернуть unexpected в случае нарушения спецификации. Все проверки - рантаймовые.
Более того, все, что делается спецификациями исключений можно довольно тривиально сделать и вручную. Обеспечив себе при этом бОльшую гибкость в реакции на unexpected, да.
Таки хинт 07.03.09 10:53  
Автор: Heller <Heller> Статус: Elderman
<"чистая" ссылка>
> Ни фига не хинт. Компилер должен сгенерировать код, который
> ОБЯЗАН дернуть unexpected в случае нарушения спецификации.
Ну, размер кода сейчас уже наверное нигде не критичен.

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

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

А вот пример того, как этот хинт помогает при оптимизации:
http://blogs.msdn.com/larryosterman/archive/2006/03/22/558390.aspx

ИМХО, использование throw() для тривиальных функций типа
bool empty() const throw() {return content.size();}
может все же оказаться полезыным, и в то же время безопасным.
Таки не *просто* хинт 07.03.09 22:29  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> > Ни фига не хинт. Компилер должен сгенерировать код,
> который
> > ОБЯЗАН дернуть unexpected в случае нарушения
> спецификации.
> Ну, размер кода сейчас уже наверное нигде не критичен.
>
> > Все проверки - рантаймовые.
> Только в случае если эксепшн все же вылетит - это
> исключительная ситуация, быстродействие которой не
> критично.
Нет, функция, которая ничего не ловит может не иметь try блока. В случае с исключениями он нужен всегда (особенно при асинхронных исключениях типа VC-шных /EHa) и вот тут уже платит не тот кто испольует (исключение), а все.

> > Более того, все, что делается спецификациями
> исключений
> > можно довольно тривиально сделать и вручную. Обеспечив
> себе
> > при этом бОльшую гибкость в реакции на unexpected, да.
>
> А вот пример того, как этот хинт помогает при оптимизации:
> http://blogs.msdn.com/larryosterman/archive/2006/03/22/5583
> 90.aspx
Как описано в бусте: самая большая проблема со спецификациями в том, что программисты имеют тенденцию понимать их не так, как они на самом деле работают. Это не хинт компилятору, что исключения не бросаются (это он может обнаружить и просто посмотрев на тело), это ТРЕБОВАНИЕ обеспечить В РАНТАЙМЕ отсутствие иных исключений, кроме специфицированных. Если исключения асинхронные - в любом месте может случиться любое исключение и в эту простешую функцию добавится еще и try блок, который будет ловить и перебрасывать "хорошие" исключения и вызывать unexpected для "плохих". Если бы спецификации не было то же самое асинхронное исключение просто раскрутило бы стек этой функции и прошло дальше незамеченным.

> ИМХО, использование throw() для тривиальных функций типа
> bool empty() const throw() {return content.size();}
> может все же оказаться полезыным, и в то же время
> безопасным.
Для инлайновых функций вообще никаких спецификаций никогда не следует указывать.
Я тоже не вижу особого смысла. Тем более, что спецификации... 06.03.09 21:51  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Я вот начал их использовать, но по-правде говоря не вижу
> большого в них смысла. Какое ваше мнение на этот счет?
Я тоже не вижу особого смысла. Тем более, что спецификации исключений не входят в сигнатуру функции и в принципе при определенном везении можно огрести трудноуловимых проблем.

> Стоит ли по каждому поводу лепить throw(...)? Очень многие
> функции работают с динамической памятью и эксепшены могут
> теоретически вылетать очень запросто. С другой стороны если
А при чем здесь память? Вообще то эксепшоны должны выкидываться в ответ на любую непредвиденную ситуацию (собственно эксепшон). Будь то access denied при открытии файла или невалидные данные от юзера. bad_alloc - на самом деле одно из самых редких исключений.

> памяти перестало хватать - ситуацию уже вряд ли спасешь
> эксепшенами, и можно вывалиться в unexpected(). Или другая
Зато можно спасти бэдаллоком, который ГАРАНТИРОВАННО можно бросить (в смысле стандарт требует, чтобы места под объект-исключение bad_alloc хватало ВСЕГДА, даже когда на все остальное памяти уже нет). И да, по unexpected ситуацию вообще не спасешь - можно только сделать дамп памяти для дебага или что то в том же духе. Независимо от того, сколько у тебя памяти

> ситуация: функция не должна выкидывать эксепшены, но
> теоретически где-то у нее внутри есть операции с
> указателями, и в качестве "невозможной ситуации" вполне
Ситуация не невозможная, а исключительная - разные вещи. Исключительные ситуации вполне ожидаемы.

> может вылететь эксепшн при использовании, например,
> нулевого указателя.
Аппаратные исключения кэтчатся не всегда: не всеми компиляторами и не при любых настройках (насколько я помню стандарт вообще ничего не говорит о том, как с ними работать). В VC есть два способа: поставить se_translator или catch(...) с асинхронными исключениями (/EHa)

> То есть получается, что с одной стороны, если честно
> объявлять как throw(...) все функции, которые умеют чисто
> физически выкидывать эксепшены, то приедется так объявлять
> 99% всего что пишешь. Мне конечно не сложно, но однако ж.
Да

> Если же игнорить потенциальные ошибки с указателями и
> динамической памятью - теряется вообще смысл в эксепшенах и
> потенуиальные падения системы, которые даже толком потом и
> не отловишь.
Ты ЧИВО? Эксепшоны ВООБЩЕ не предназначены для отлавливания неправильной работы с указателями (для этого есть умные указатели). Независимо от этого экспепшены сами по себе - КРАЙНЕ полезная фича плюсов, а вот спецификации этих самых исключений не используются практически нигде (кроме разве что спецификации throw() )

> В общем, я в замешательстве. Что скажете?
Не факт. То что лучше - не всегда является стандартом и... 07.03.09 06:06  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
> А при чем здесь память? Вообще то эксепшоны должны
> выкидываться в ответ на любую непредвиденную ситуацию
> (собственно эксепшон). Будь то access denied при открытии
> файла или невалидные данные от юзера. bad_alloc - на самом
> деле одно из самых редких исключений.

Не факт. То что лучше - не всегда является стандартом и возможно к применению в команде на предприятии где ты работаешь не один.

> Аппаратные исключения кэтчатся не всегда:

__try кечит практически всегда. Приведи пример, когда не всегда.

> компиляторами и не при любых настройках (насколько я помню
> стандарт вообще ничего не говорит о том, как с ними
> работать). В VC есть два способа: поставить se_translator
> или catch(...) с асинхронными исключениями (/EHa)

Добавлю про /EHa - начиная с VC++ 8.0. В ранних версиях или не работало, или работало плохо.


>
> > То есть получается, что с одной стороны, если честно
> > объявлять как throw(...) все функции, которые умеют
> чисто
> > физически выкидывать эксепшены, то приедется так
> объявлять
> > 99% всего что пишешь. Мне конечно не сложно, но однако
> ж.
> Да

Зависит от надежд получить "оптимальный" код как того обещает MS.
В принципе регрешн тесты + QA могут помочь ответить на вопрос - стоит или нет использовать.
__try не имеет никакого отношения ни к плюсам ни к плюсовым... 07.03.09 06:58  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> > Аппаратные исключения кэтчатся не всегда:
>
> __try кечит практически всегда. Приведи пример, когда не
> всегда.

__try не имеет никакого отношения ни к плюсам ни к плюсовым exception-ам. В смысле в VC плюсовые исключения реализованы поверх SEH, но во первых мешать SEH и плюсовый EH - крайне плохая идея (для этого в общем и придуманы трансляторы), а во вторых SEH доступен и не из плюсов.

> Добавлю про /EHa - начиная с VC++ 8.0. В ранних версиях
> или не работало, или работало плохо.
В общем я особо не знаю (когда было действительно необходимо - использовал трансляторы), но насколько я помню, это работало у меня и в 7-м VC (в частности 7.1, которая 2003). Здесь могу ошибаться.

> Зависит от надежд получить "оптимальный" код как того
> обещает MS.
> В принципе регрешн тесты + QA могут помочь ответить на
> вопрос - стоит или нет использовать.
Можно не только оптимизацию порушить, в статье, что я приводил вылазят проблемы с виртуальными функциями (при том что спецификация исключений в сигнатуру функции таки не входит).
Согласен, что разное, и что мешать не стоит согласен. Имел... 07.03.09 07:37  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
> __try не имеет никакого отношения ни к плюсам ни к плюсовым
> exception-ам. В смысле в VC плюсовые исключения реализованы
> поверх SEH, но во первых мешать SEH и плюсовый EH - крайне
> плохая идея (для этого в общем и придуманы трансляторы), а
> во вторых SEH доступен и не из плюсов.

Согласен, что разное, и что мешать не стоит согласен. Имел ввиду, что в самом крайнем случае, можно обработать SE и re-throw() свой С++ екзепшн класс: public std::exception, еслиб возникла необходимость такая необходимость или использование транслятора SE в EH по какой-то причине нехочется (для каждого треда).
Достаточно часто для функции можно быть уверенным близко к... 07.03.09 00:27  
Автор: Heller <Heller> Статус: Elderman
<"чистая" ссылка>
> А при чем здесь память? Вообще то эксепшоны должны
> выкидываться в ответ на любую непредвиденную ситуацию
> (собственно эксепшон). Будь то access denied при открытии
> файла или невалидные данные от юзера. bad_alloc - на самом
> деле одно из самых редких исключений.
Достаточно часто для функции можно быть уверенным близко к 100%, что она не кидает никаких эксепшенов. В том-то и дело, что bad_alloc - это тот самый эксепшен, который часто даже почти в тривиальной функции теоретически может возникнуть. Ну, допустим написал я функцию, которая внутри где-то у себя ресайзит вектор. И это единственное место где она может упать. Могу ли я писать throw() в декларации? Все же bad_alloc - штука крайне редкая, и в 99.99% приложений вообще никогда не встретится.

> Зато можно спасти бэдаллоком, который ГАРАНТИРОВАННО можно
> бросить (в смысле стандарт требует, чтобы места под
> объект-исключение bad_alloc хватало ВСЕГДА, даже когда на
> все остальное памяти уже нет). И да, по unexpected ситуацию
> вообще не спасешь - можно только сделать дамп памяти для
> дебага или что то в том же духе. Независимо от того,
> сколько у тебя памяти
Я может быть слишком халатен, но мой подход таков: "Нет памяти, значит покупай железо". Память находится вне компетенции девелопера. На bad_alloc я просто плевал. Никак его не обрабатываю (кроме сообщения "купи памяти"), и даже не пытаюсь спасти рантайм. Пусть упадет хоть как - не мое дело. Но в то же время не смотря на мою халатность писать для функции throw(), если она работает с памятью, как-то уж даже для меня - слишком. Но с другой стороны почему бы и нет? Вот и колеблюсь.

> Ситуация не невозможная, а исключительная - разные вещи.
> Исключительные ситуации вполне ожидаемы.
Допустим я реализую что-то с указателями ("умные" не всегда подходят) - такое случается, бывает. И вот я отладил уже на 100% какую-нибудь функцию и уверен вообще совсем и полностью, что бага нет. Имею я право писать throw()? Или все же то что я уверен еще не значит, что я имею право на throw()? Таки и assert-ы бывает срабатывают.

> Аппаратные исключения кэтчатся не всегда: не всеми
> компиляторами и не при любых настройках (насколько я помню
> стандарт вообще ничего не говорит о том, как с ними
> работать). В VC есть два способа: поставить se_translator
> или catch(...) с асинхронными исключениями (/EHa)
Ну да, я главным образом о Винде говорю.


> > 99% всего что пишешь. Мне конечно не сложно, но однако
> ж.
> Да
Кстати, есть еще и чисто психологически момент: когда смотришь на объявление функции что-нибудь типа
ret_type getSomeStuff();
то ты спокоен. Когда же смотришь на объявление вроде такого:
ret_type getSomeStuff() throw(...);
то уже подходешь к функции более серьезно. Ну а если еще и конкретные эксепшены указаны - то вообще обработаешь каждый в отдельности с гораздо большей вероятностью, чем при "голом" объявлении.

> Ты ЧИВО? Эксепшоны ВООБЩЕ не предназначены для отлавливания
> неправильной работы с указателями (для этого есть умные
> указатели). Независимо от этого экспепшены сами по себе -
> КРАЙНЕ полезная фича плюсов, а вот спецификации этих самых
> исключений не используются практически нигде (кроме разве
> что спецификации throw() )
Немного не так выразился. Но однако повторюсь, что нет-нет, да обычные опасные указатели все же приходится использовать. Добавь сюда работу со старыми библиотеками (никуда не денешься) и сопровождение старого кода. Под никсами можно обрабатывать сигналы, а под виндой единственственный вариант, какой я вижу - эксепшены. Указатели и аллокации я привел потому что это самые трудно контролируемые ошибки, которые сразу же приводят к падению, если грамотно их не обработать. С остальными ошибками все же как-то проще, согласись.

Кстати, еще одно преимущество использования throw() - дополнительные компиляторные оптимизации, которые могут быть произведены.
У меня один раз было... Недель назад мемори лик. 07.03.09 06:15  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
> 100%, что она не кидает никаких эксепшенов. В том-то и
> дело, что bad_alloc - это тот самый эксепшен, который часто
> даже почти в тривиальной функции теоретически может
> возникнуть.
> Ну, допустим написал я функцию, которая внутри
> где-то у себя ресайзит вектор. И это единственное место где
> она может упать. Могу ли я писать throw() в декларации? Все
> же bad_alloc - штука крайне редкая, и в 99.99% приложений
> вообще никогда не встретится.

У меня один раз было... Недель назад мемори лик.

> Я может быть слишком халатен, но мой подход таков: "Нет
> памяти, значит покупай железо". Память находится вне
> компетенции девелопера.

Ну если это не баг, конечно. А так -100% согласен.

> Кстати, еще одно преимущество использования throw() -
> дополнительные компиляторные оптимизации, которые могут
> быть произведены.

Вроде так обещает MS. Но надо смотреть в каздом кнкретном случае. Может хоть asm листинг покажет?
Хых. Ты должен гарантировать это не только для самой... 07.03.09 03:03  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Достаточно часто для функции можно быть уверенным близко к
> 100%, что она не кидает никаких эксепшенов. В том-то и
Хых. Ты должен гарантировать это не только для самой функции, но и для всего кода, который может быть достигнут, не выходя из нее (функций любого уровня вложености, которые она вызывает даже косвенно). Для любой нетривиальной функции "задолбаешься пыль глотать".

> дело, что bad_alloc - это тот самый эксепшен, который часто
> даже почти в тривиальной функции теоретически может
> возникнуть. Ну, допустим написал я функцию, которая внутри
> где-то у себя ресайзит вектор. И это единственное место где
> она может упать. Могу ли я писать throw() в декларации? Все
Зачем?
Вот тебе ЦИТАТА из ISO/IEC 14882
23.2.6 Class template vector [vector]
void resize(size_type sz);
void resize(size_type sz, const T& c);

---
Видишь где нибудь спецификацию? Тебе ничего не обещают, а ты значит рвешься пообещать.

> же bad_alloc - штука крайне редкая, и в 99.99% приложений
> вообще никогда не встретится.
Я о том и говорил. Бэдаллок - это не тот эксепшн, который надо принимать в рассчет в первую очередь

> Я может быть слишком халатен, но мой подход таков: "Нет
> памяти, значит покупай железо". Память находится вне
> компетенции девелопера. На bad_alloc я просто плевал. Никак
> его не обрабатываю (кроме сообщения "купи памяти"), и даже
> не пытаюсь спасти рантайм. Пусть упадет хоть как - не мое
И не надо спасать - просто не лови (если не собираешься) и не специфицируй - неотловленное исключение на выходе из main все так же прибьет твое приложение.

> дело. Но в то же время не смотря на мою халатность писать
> для функции throw(), если она работает с памятью, как-то уж
> даже для меня - слишком. Но с другой стороны почему бы и
> нет? Вот и колеблюсь.
Не пиши.

> > Ситуация не невозможная, а исключительная - разные
> вещи.
> > Исключительные ситуации вполне ожидаемы.
> Допустим я реализую что-то с указателями ("умные" не всегда
> подходят) - такое случается, бывает. И вот я отладил уже на
Такое "бывает" разве что в third-party коде. Ты еще и за него отвечать хочешь?

> 100% какую-нибудь функцию и уверен вообще совсем и
> полностью, что бага нет. Имею я право писать throw()? Или
> все же то что я уверен еще не значит, что я имею право на
> throw()? Таки и assert-ы бывает срабатывают.
Имеешь право. Вот только я не вижу особой разницы между unexpected(), если ты сфейлил свои спецификации и terminate(), если ты просто не словил исключение. Если же ты собираешься сделать set_unexpected и перебрасывать там валидное исключение, то стоит вспомнить, что у тебя один unexpected_handler на всю программу и надо сделать его очень умным, чтобы переброшенное исключение соответствовало всем спецификациям.

> > Аппаратные исключения кэтчатся не всегда: не всеми
> > компиляторами и не при любых настройках (насколько я
> помню
> > стандарт вообще ничего не говорит о том, как с ними
> > работать). В VC есть два способа: поставить
> se_translator
> > или catch(...) с асинхронными исключениями (/EHa)
> Ну да, я главным образом о Винде говорю.
Ну дык и используй se_translator, собственно спецификации исключений тебе ВООБЩЕ не помогут в случае с разыменованием null-поинтеров. Более того, в транслированном эксепшоне ты можешь иметь всю информацию, которая вообще доступна в SEH. На всякий случай напомню, что SE транслятор ставится не на весь рантайм, а на поток, так что надо их ставить во все потоки, где ты ожидаешь выбрасывания SEH-исключений.

> > > 99% всего что пишешь. Мне конечно не сложно, но
> однако
> > ж.
> > Да
> Кстати, есть еще и чисто психологически момент: когда
> смотришь на объявление функции что-нибудь типа
> ret_type getSomeStuff();
> то ты спокоен. Когда же смотришь на объявление вроде
> такого:
> ret_type getSomeStuff() throw(...);
> то уже подходешь к функции более серьезно. Ну а если еще и
> конкретные эксепшены указаны - то вообще обработаешь каждый
> в отдельности с гораздо большей вероятностью, чем при
> "голом" объявлении.
У нас и так непростая работа, чтобы мучать себя еще и этим :-)


> Немного не так выразился. Но однако повторюсь, что нет-нет,
> да обычные опасные указатели все же приходится
> использовать. Добавь сюда работу со старыми библиотеками
А я не говорю, что надо везде использовать смартпоинтеры. Просто когда ты работаешь с неумными, и бросаешь хардварный эксепшн, плюсы вообще НИЧЕМ тебе помочь не могут. Ни эксепшоны, ни их спецификации не приспособлены для вылавливания таких ситуаций. Так что или умные указатели или упавшая программа (можно еще использовать расширения данной конкретной реализации для вылавливания хардварных исключений).

> (никуда не денешься) и сопровождение старого кода. Под
> никсами можно обрабатывать сигналы, а под виндой
Хых. Из хэндлера сигналов у тебя есть либо long_jmp либо exit. В VC же можно транслировать "сигналы" в обычные плюсовые исключения и работать с ними как обычно.

> единственственный вариант, какой я вижу - эксепшены.
Да, но ты его видишь СОВЕРШЕННО не там. Никакие спецификации исключений не помогут тебе отловить разыменование нулпоинтера (буду повторять, пока ты не осознаешь :-) ).

> Указатели и аллокации я привел потому что это самые трудно
> контролируемые ошибки, которые сразу же приводят к падению,
> если грамотно их не обработать. С остальными ошибками все
> же как-то проще, согласись.
Не согласен. Неинициализированные переменные или ошибки синхронизации гораздо хуже. Ошибка доступа к памяти мгновенно вываливает тебя в дебаггер и вся поднаготная ошибки у тебя на виду. Нехватка памяти - вообще не ошибка, ее действительно можно не обрабатывать.

> Кстати, еще одно преимущество использования throw() -
> дополнительные компиляторные оптимизации, которые могут
> быть произведены.
Хыхы. Скорее ДЕоптимизации.
http://www.gotw.ca/publications/mill22.htm (+ссылки в конце статьи)

И небольшая цитата от разработчиков буста (эх, может я когда нибудь и буду знать плюсы так как они):
http://www.boost.org/development/requirements.html#Exception-specification
"For example, some compilers turn off inlining if there is an exception-specification. Some compilers add try/catch blocks. Such pessimizations can be a performance disaster which makes the code unusable in practical applications.

Although initially appealing, an exception-specification tends to have consequences that require very careful thought to understand. The biggest problem with exception-specifications is that programmers use them as though they have the effect the programmer would like, instead of the effect they actually have.

A non-inline function is the one place a "throws nothing" exception-specification may have some benefit with some compilers."
У меня нет под рукой сейчас исходников (не держу дома :-)),... 07.03.09 11:14  
Автор: Heller <Heller> Статус: Elderman
<"чистая" ссылка>
> Вот тебе ЦИТАТА из ISO/IEC 14882
У меня нет под рукой сейчас исходников (не держу дома :-)), но что-то мне подсказывает, что они и для empty() не объявляют throw(). Хотя могли бы. Это скорее вопрос исторический.

> Такое "бывает" разве что в third-party коде. Ты еще и за
> него отвечать хочешь?
Не вижу большой трудности:
catch(...) {
writeLog("Упало здесь");
throw MyOwnException();
}

> Имеешь право. Вот только я не вижу особой разницы между
> unexpected(), если ты сфейлил свои спецификации и
> terminate(), если ты просто не словил исключение. Если же
> ты собираешься сделать set_unexpected и перебрасывать там
> валидное исключение, то стоит вспомнить, что у тебя один
> unexpected_handler на всю программу и надо сделать его
> очень умным, чтобы переброшенное исключение соответствовало
> всем спецификациям.
Разница в том что имеет разработчик, который будет жергать функции моего класса.

[skipped, ибо в целом согласен]

> Да, но ты его видишь СОВЕРШЕННО не там. Никакие
> спецификации исключений не помогут тебе отловить
> разыменование нулпоинтера (буду повторять, пока ты не
> осознаешь :-) ).
Не осознал. Пользователь нажал на кнопку. В обработчике попытался разыменоваться нулл-поинтер. Я словил эксепшен. В функции, где это непосредственно произошло - отписываю в лог, что "вот здесь упало", а наверх пробрасываю типизированный эксепшн по которому могу уже принять какое-то решение (например, извиниться за ошибку в данном конерктном функционале, но продолжить работу всей остальной программы).

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

> http://www.gotw.ca/publications/mill22.htm (+ссылки в конце
> http://www.boost.org/development/requirements.html#Exceptio
Интересно. Да, таки многое стало понятнее.

Вывод, какой я сделал: либо throw(...) в качестве меты, если хочу дополнительно подчеркнуть, что к функции надо отнестись внимательнее, либо throw() для случая совсем банальных функций типа getsize() в целях оптимизации (см. мой ответ выше по ветке).
Из VC9 stl-я: 07.03.09 22:20  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> > Вот тебе ЦИТАТА из ISO/IEC 14882
> У меня нет под рукой сейчас исходников (не держу дома :-)),
> но что-то мне подсказывает, что они и для empty() не
Из VC9 stl-я:
	void resize(size_type _Newsize)
		{	// determine new length, padding with _Ty() elements as needed
		resize(_Newsize, _Ty());
		}

	void resize(size_type _Newsize, _Ty _Val)
		{	// determine new length, padding with _Val elements as needed
		if (size() < _Newsize)
			_Insert_n(end(), _Newsize - size(), _Val);
		else if (_Newsize < size())
			erase(begin() + _Newsize, end());
		}

---
Спецификаций нет даже для ресайза.

> объявляют throw(). Хотя могли бы. Это скорее вопрос
> исторический.
Нет, не исторический. В C++0x к тем же ресайзам не моргнув глазом добавили концепты. Ну а первое появление спецификаций исключений как раз и появилось в стандарте - даже об "обратной совместимости" думать не надо.

> > Такое "бывает" разве что в third-party коде. Ты еще и
> за
> > него отвечать хочешь?
> Не вижу большой трудности:
> catch(...) {
> writeLog("Упало здесь");
> throw MyOwnException();
> }
Хых. И зачем тебе это? Точно так же ты можешь просто сделать catchall на самом верхнем уровне и сделать там "Упало здесь". Вот только каждая спецификация на пути это catch-rethrow. Не очень эффективно.

> Разница в том что имеет разработчик, который будет жергать
> функции моего класса.
Нет, он будет либо иметь эксепшн из твоего класса, если ты соответствуешь собственным спецификациям, либо unexpected - если не соответствуешь. И на хрена ему твой unexpected? Может у него другие мысли по поводу того, как он собирается следить за исключениями?

> > Да, но ты его видишь СОВЕРШЕННО не там. Никакие
> > спецификации исключений не помогут тебе отловить
> > разыменование нулпоинтера (буду повторять, пока ты не
> > осознаешь :-) ).
> Не осознал. Пользователь нажал на кнопку. В обработчике
> попытался разыменоваться нулл-поинтер. Я словил эксепшен. В
Хорошо, раз не осознал, то для начала скажи КАКОЙ эксепшон ты словил?

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

> какое-то решение (например, извиниться за ошибку в данном
> конерктном функционале, но продолжить работу всей остальной
> программы).
Ага. Именно для этого сделаны эксепшены. Их спецификации сделаны для другого и это другое в целом не нужно.

> > http://www.gotw.ca/publications/mill22.htm (+ссылки в
> конце
> >
> http://www.boost.org/development/requirements.html#Exceptio
> Интересно. Да, таки многое стало понятнее.
>
> Вывод, какой я сделал: либо throw(...) в качестве меты,
> если хочу дополнительно подчеркнуть, что к функции надо
> отнестись внимательнее, либо throw() для случая совсем
> банальных функций типа getsize() в целях оптимизации (см.
> мой ответ выше по ветке).
Ага.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 1 s   Design: Vadim Derkach