Re[9]: Не выпендриваюсь ли я?
От: Cyberax Марс  
Дата: 27.07.07 17:48
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

C>>Конечно, в некоторых случаях это не очень удобно — в ядерном программировании, например.

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

MSS>В ядрах же другие проблемы, там, например, нет рантайма поддержки Си++ эксепшнов — только Си/Win32, которые __try/__except(EXCEPTION_EXECUTE_HANDLER).

Это понятно — просто технические ограничения. В Линуксе точно так же — в ядре вообще без извращений только на чистом С можно писать.
Sapienti sat!
Re[11]: Не выпендриваюсь ли я?
От: minorlogic Украина  
Дата: 27.07.07 17:49
Оценка:
Я приведу пример из своего опыта.

Я видел людей которые начинали пользоваться ексепшенами и RIIA и прониклись. Ни разу не встречал чтобы ктото из них хотел вести оьрабьотку ошибок через возвращаемые значения. Да и флеймить об этом в 2007 году даже не с руки.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[10]: Не выпендриваюсь ли я?
От: minorlogic Украина  
Дата: 27.07.07 18:46
Оценка:
Здравствуйте, Cyberax, Вы писали:

MSS>>В ядрах же другие проблемы, там, например, нет рантайма поддержки Си++ эксепшнов — только Си/Win32, которые __try/__except(EXCEPTION_EXECUTE_HANDLER).

C>Это понятно — просто технические ограничения. В Линуксе точно так же — в ядре вообще без извращений только на чистом С можно писать.

Так исключения тут причем ? это другой язык , тут все в ручную by design.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[12]: Не выпендриваюсь ли я?
От: Maxim S. Shatskih Россия  
Дата: 27.07.07 18:54
Оценка:
X>void f()
X>{
X> if(!SUCCESS(Osilit1()))
X> NeOsilil();
X> if(!SUCCESS(Osilit2()))
X> NeOsilil();
X> if(!SUCCESS(Osilit3()))
X> NeOsilil();
X> if(!SUCCESS(Osilit4()))
X> NeOsilil();
X> if(!SUCCESS(Osilit5()))
X> NeOsilil();
X>}
X>[/code]


Ну в реале-то оно не так. В реале, если обломилась Osilit2, то надо сделать undo Osilit1, и обработчики облома у всех разные.

X>
X>void f()
X>{
X>  try {
X>    Osilit1();
X>    Osilit2();
X>    Osilit3();
X>    Osilit4();
X>    Osilit5();
X>  catch(...)
X>  {
X>    NeOsilil();
X>  }
X>}
X>


Так бывает только в простейшем случае. В реале же, если обломилась Osilit1, то обработчик облома один, а если Osilit2 — то уже другой.

X>И второй вопрос. Что вы будите делать без обработки исключений когда у вас возникает ошибка во время конструирования объекта?


Это отвратительный ляпсус в Си++. Автор книг про COM Крайг Брокшмидт вообще советовать _не класть в конструктор ничего, что может обломиться_, а сделать еще метод Init.

И он прав.

X>Как решается эта проблема с механизмом исключений понятно. Например в моем коде вероятность ошибки во время конструирования вполне реальна


Я бы переписал код (если это Си++) так, как предлагает Брокшмидт.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[12]: Не выпендриваюсь ли я?
От: Maxim S. Shatskih Россия  
Дата: 27.07.07 18:56
Оценка:
M>Да и флеймить об этом в 2007 году даже не с руки.

Почему? огромное количество кода написано вообще на Си или на Си++ без использования throw.

Например, значительная часть серьезного опен-сорса.

Понимаете, подход "есть фича, надо юзать" — это детство.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[11]: Не выпендриваюсь ли я?
От: Maxim S. Shatskih Россия  
Дата: 27.07.07 18:58
Оценка:
M>Так исключения тут причем ? это другой язык , тут все в ручную by design.

Превед

__try/__except(EXCEPTION_EXECUTE_HANDLER) будет работать и в Си++.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[13]: Не выпендриваюсь ли я?
От: Cyberax Марс  
Дата: 27.07.07 19:29
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

M>>Да и флеймить об этом в 2007 году даже не с руки.

MSS>Почему? огромное количество кода написано вообще на Си или на Си++ без использования throw.
MSS>Например, значительная часть серьезного опен-сорса.
Например, в ядре Линукса используется "эмуляция" исключений в виде "goto out/goto error_exit". Как раз чтобы убрать горы макаронного кода проверок.
Sapienti sat!
Re[13]: Не выпендриваюсь ли я?
От: Cyberax Марс  
Дата: 27.07.07 19:35
Оценка: 1 (1)
Здравствуйте, Maxim S. Shatskih, Вы писали:

MSS>Ну в реале-то оно не так. В реале, если обломилась Osilit2, то надо сделать undo Osilit1, и обработчики облома у всех разные.

Пожалуйста:
void f()
{
    ON_BLOCK_EXIT(guard,&Osilit1);
    Osilit2();
    Osilit3();
    Osilit4();
    Osilit5();

    guard.dismiss(); //Отключает guard'а.
}

Какие проблемы?

Я уже много лет использую слегка модифицированый код отсюда http://www.ddj.com/dept/cpp/184403758 для подобного:
FILE *fl=fopen("/adf/adsfh","wb");
ON_BLOCK_EXIT(&fclose,fl);

fprintf("...");
throw my_exception("Caput!");


Для C++'ного стиля с RAII так вообще:
std::ofstream str("/adsfadf");

str<<"Hello, world!"<<std::endl;
throw my_exception("Caput!");


MSS>Это отвратительный ляпсус в Си++. Автор книг про COM Крайг Брокшмидт вообще советовать _не класть в конструктор ничего, что может обломиться_, а сделать еще метод Init.

Ага. Анекдот из шести слов: "C++ best practice from COM creator".
Sapienti sat!
Re[14]: Не выпендриваюсь ли я?
От: Maxim S. Shatskih Россия  
Дата: 28.07.07 00:02
Оценка:
C>Пожалуйста:
C>
C>void f()
C>{
C>    ON_BLOCK_EXIT(guard,&Osilit1);
C>    Osilit2();
C>    Osilit3();
C>    Osilit4();
C>    Osilit5();

C>    guard.dismiss(); //Отключает guard'а.
C>}
C>

C>Какие проблемы?

Код для undo где писать?

C>Ага. Анекдот из шести слов: "C++ best practice from COM creator".


Почему анекдот? очень здравые у него там идеи. Пользуешься, все работает, проблем в реальных проектах не возникает.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[14]: Не выпендриваюсь ли я?
От: Maxim S. Shatskih Россия  
Дата: 28.07.07 00:04
Оценка:
C>Например, в ядре Линукса используется "эмуляция" исключений в виде "goto out/goto error_exit". Как раз чтобы убрать горы макаронного кода проверок.

Оно и в виндах так используется. А еще в виндах используется нечто вроде:

try
{
...
}
finally
{
if( Object1Initialized )
DestroyObject1();
if( Object2Initialized )
DestroyObject2();
}

Решительно не понимаю, чем этот ужас лучше, чем проверка и undo сразу (лексически) после проверки.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[15]: Не выпендриваюсь ли я?
От: Cyberax Марс  
Дата: 28.07.07 00:42
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

C>>
C>>void f()
C>>{
C>>    ON_BLOCK_EXIT(guard,&Osilit1);
C>>    Osilit2();
C>>    Osilit3();
C>>    Osilit4();
C>>    Osilit5();
C>>    guard.dismiss(); //Отключает guard'а.
C>>}
C>>

C>>Какие проблемы?
MSS>Код для undo где писать?
В Osilit1. Реально обычно нужно вызывать cleanup-функции. В редких случаях можно написать локальный класс для какого-то уж слишком спецефического действия.

Если нужно для cleanup-функции добавить параметры — используем boost::bind. Тем более, что после SmallBufferOptimization связка boost::bind+boost::function работает всего где-то в 2 раза медленнее, чем простой вызов функции.

C>>Ага. Анекдот из шести слов: "C++ best practice from COM creator".

MSS>Почему анекдот? очень здравые у него там идеи. Пользуешься, все работает, проблем в реальных проектах не возникает.
Ага, конечно...
Sapienti sat!
Re[15]: Не выпендриваюсь ли я?
От: Cyberax Марс  
Дата: 28.07.07 00:47
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

MSS>Оно и в виндах так используется. А еще в виндах используется нечто вроде:

MSS>try
MSS>{
MSS> ...
MSS>}
MSS>finally
MSS>{
MSS> if( Object1Initialized )
MSS> DestroyObject1();
MSS> if( Object2Initialized )
MSS> DestroyObject2();
MSS>}
MSS>Решительно не понимаю, чем этот ужас лучше, чем проверка и undo сразу (лексически) после проверки.
Меньше места занимает. Вот такой макаронный код:
char *str1=malloc(..);
if (doSomething(str1))
{
   free(str1);
   return -1;
}

char *str2=malloc(...);
if (doSomething2(str2))
{
   free(str1);
   free(str2);
   return -1;
}


Превращается в намного более чистый и компактный:
int err=0;

char *str1=malloc(...);
if (err=doSomething(str1)) goto err_exit;

char *str2=malloc(...);
if (err=doSomething(str2)) goto err_exit;

return 0;

err_exit:
   free(str1);
   free(str2);
   return err;
Sapienti sat!
Re[15]: Не выпендриваюсь ли я?
От: xfruit Германия http://floomby.ru
Дата: 28.07.07 11:07
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

C>>Например, в ядре Линукса используется "эмуляция" исключений в виде "goto out/goto error_exit". Как раз чтобы убрать горы макаронного кода проверок.


MSS>Оно и в виндах так используется. А еще в виндах используется нечто вроде:


MSS>try

MSS>{
MSS> ...
MSS>}
MSS>finally
MSS>{
MSS> if( Object1Initialized )
MSS> DestroyObject1();
MSS> if( Object2Initialized )
MSS> DestroyObject2();
MSS>}

MSS>Решительно не понимаю, чем этот ужас лучше, чем проверка и undo сразу (лексически) после проверки.


Бизнес логика приложения отделена от логики обработки исключительных ситуаций.
Re[13]: Не выпендриваюсь ли я?
От: minorlogic Украина  
Дата: 28.07.07 20:03
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

Я имел ввиду флейм о преимуществах даваемых ексепшенами перед ручной обработкой ошибок.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[12]: Не выпендриваюсь ли я?
От: minorlogic Украина  
Дата: 28.07.07 20:18
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

M>>Так исключения тут причем ? это другой язык , тут все в ручную by design.


MSS>Превед


MSS>__try/__except(EXCEPTION_EXECUTE_HANDLER) будет работать и в Си++.


Повторюсь в раз 4-й , ексепшены в С++ by design расчитанны на использование RAII

http://en.wikipedia.org/wiki/RAII

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

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

2. Посколько на исключениях не завязанна логика то и делать в обработчиках, это сообщить комунмть о проблеме и решить что делать дальше.

3. Вся транзакционность , логика, управление ресурсами идет через RAII и ни в коем случае не через обработчик исключения(это грубое нарушение инкапсуляции и жесткое увеличение связанности).

http://en.wikipedia.org/wiki/RAII
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[13]: Не выпендриваюсь ли я?
От: minorlogic Украина  
Дата: 28.07.07 20:18
Оценка:
Для меня ваши слова звучат заблуждениям. Если вам интерессно , приведите пример и попробуем его вместе отрефакторить.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[13]: Не выпендриваюсь ли я?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 29.07.07 11:08
Оценка:
Здравствуйте, minorlogic, Вы писали:

MSS>>Превед :)


MSS>>__try/__except(EXCEPTION_EXECUTE_HANDLER) будет работать и в Си++.


M>Повторюсь в раз 4-й , ексепшены в С++ by design расчитанны на использование RAII


M>http://en.wikipedia.org/wiki/RAII


Вот именно что "рассчитаны". Но этот расчёт базируется, по сути, на одном — на том, что разработчики считают, что если есть RAII, то ничего иного не должно уже быть, и делать try-finally в языке нет смысла.

Проблемой в этом подходе является то, что когда действие, которое надо откатить при выходе из функции, усложняется — вместо естественного подхода начинается искусственное выделение действий в RAII-класс. Из того, что мне реально приходилось строить — действие при входе в функцию и откат при выходе:

1. Замена значения внешней переменной.
2. Установка обработчика сигнала.
3. Сложные комбинации присваивания и вызова внешних функций (модификация части окружения).
4. Транзакционные операции с внешним хранилищем.

В результате — приходилось писать для таких вещей особый класс, и действие функции становилось менее понятным при чтении (как минимум приходилось ставить комментарий, что тут важная часть функциональности ушла во вспомогательный класс), вместо того, чтобы сделать

try {
  подготовка обстановки;
  работа;
} finally {
  восстановление обстановки;
}


что, по-моему, в разы более ясно для понимания.

Вот потому мне и не нравится позиция разработчиков C++. Типичное "сегодня в колбасе потребности нет".

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


Весьма странное утверждение (ещё одно?)
Может, в ряде задач так оно и будет. А вот в построении, например, сетевого взаимодействия со сложной логикой без достаточного количества обработчиков (значительно больше, чем на пальцах) не обойтись, потому что

1) Оно не имеет права вылетать только от того, что сокет закрыли с другой стороны (да, тут уже свойство библиотеки — она кидает исключение в таком случае).
2) внутренний событийный движок не должен дохнуть от того, что где-то в недрах одного обработчика произошло исключение.
3) само собой, очистные работы (удаление обработки запроса по закрытию соединения или присылке отказа от обработки) не должны прерываться ни в коем случае, кроме какой-то глобальной неустранимой проблемы вроде порчи динамической кучи), и их код состоит из сплошных try вокруг одного действия и catch с логгингом вокруг него.

Вот сейчас грепнул — 113 try'ев. После очистки от стилевых (защита от перезагрузки модулей) — 94. Это уже рабочий комплект.

Или 94 — это ещё "на пальцах"?

M>1. Исключение вызывается только в случае когда мы не можем продолжать выполнение логики работы или кода.


Да, не можем. Но не всей программы, а одного соединения. Остальное должно выживать.
Кстати, это совсем не сетевая специфика. Возьмём к примеру фотошоп. Должен ли он дохнуть целиком оттого, что один фильтр навернулся? Очевидно, нет. Мы можем разве что посоветовать юзеру "сохранись, выйди и перезапустись, программа уже в подозрительном состоянии". Но выбивать всю программу — ой нельзя.

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


В "мелком" случае это действительно стилевщина и вкусовщина:) Но не в большом комплексе.

M>2. Посколько на исключениях не завязанна логика то и делать в обработчиках, это сообщить комунмть о проблеме и решить что делать дальше.


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

M>3. Вся транзакционность , логика, управление ресурсами идет через RAII и ни в коем случае не через обработчик исключения(это грубое нарушение инкапсуляции и жесткое увеличение связанности).


M>http://en.wikipedia.org/wiki/RAII


Скучная страничка. Там слишком узко понимают "потребление ресурсов". См. выше про finally.
The God is real, unless declared integer.
Re[14]: Не выпендриваюсь ли я?
От: minorlogic Украина  
Дата: 29.07.07 11:25
Оценка:
Прошу воспринимать мой пост как рекомендации . Best practices
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[15]: Не выпендриваюсь ли я?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 29.07.07 11:36
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Прошу воспринимать мой пост как рекомендации . Best practices


1. Это невозможно воспринимать как "best practices", пока есть массовые случаи противоречия постулатам (типа "RAII правильно, всё остальное не нужно"). Если Ваш случай проще... что ж, могу просто позавидовать. Мне такая простота недоступна, и "колбаса" нужна.

2. По процедуре: Вы злоупотребляете, jIMHO, срезанием квотинга. Ни в почте, ни в моём показе (я воспринимаю только линейный показ, дерево в таких форумах для меня громоздко и неудобно) непонятно, к чему относятся замечания. Особенно предыдущее про "звучат заблуждениями".
The God is real, unless declared integer.
Re[14]: Не выпендриваюсь ли я?
От: minorlogic Украина  
Дата: 29.07.07 11:54
Оценка:
Здравствуйте, netch80, Вы писали:

N>В результате — приходилось писать для таких вещей особый класс, и действие функции становилось менее понятным при чтении (как минимум приходилось ставить комментарий, что тут важная часть функциональности ушла во вспомогательный класс), вместо того, чтобы сделать


N>
N>try {
N>  подготовка обстановки;
N>  работа;
N>} finally {
N>  восстановление обстановки;
N>}
N>


N>что, по-моему, в разы более ясно для понимания.

А по моему это довольно архаичный стиль и уж точно хуже для понимания. Спорить по этому поводу я не готов и нет желания, останемся при своих. Для меня вполне узнаваемым будет код с объектами transaction (command ми т.п.).

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


N>Весьма странное утверждение (ещё одно?)

Это моя личная рекомендация.

N>Может, в ряде задач так оно и будет. А вот в построении, например, сетевого взаимодействия со сложной логикой без достаточного количества обработчиков (значительно больше, чем на пальцах) не обойтись, потому что

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

N>Вот сейчас грепнул — 113 try'ев. После очистки от стилевых (защита от перезагрузки модулей) — 94. Это уже рабочий комплект.


N>Или 94 — это ещё "на пальцах"?

Я сразу подозреваю пробелы в дизайне и логику приложения использующуюся в блоках try catch


M>>1. Исключение вызывается только в случае когда мы не можем продолжать выполнение логики работы или кода.


N>Да, не можем. Но не всей программы, а одного соединения. Остальное должно выживать.

N>Кстати, это совсем не сетевая специфика. Возьмём к примеру фотошоп. Должен ли он дохнуть целиком оттого, что один фильтр навернулся? Очевидно, нет. Мы можем разве что посоветовать юзеру "сохранись, выйди и перезапустись, программа уже в подозрительном состоянии". Но выбивать всю программу — ой нельзя.
С этим странно спорить и комментировать, не знаю с чего вы решили что я утверждал обратное.

M>>2. Посколько на исключениях не завязанна логика то и делать в обработчиках, это сообщить комунмть о проблеме и решить что делать дальше.


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

"сообщить комунмть" это не значит выкинуть окошко. Это означает проинформировать вызывающую сторону о невозможности выполнить действие.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.