Re[21]: Checked exceptions... зло или добро?
От: Павел Кузнецов  
Дата: 20.07.05 05:12
Оценка: -1 :)
VladD2,

ПК>> В C++ процесс освобождения памяти вполне детерминирован. В чем

ПК>> проблема-то?

V> В том, что это красивая сказака не имеющая ничего общего с жизнью.


Видимо, у нас, все-таки, жизнь разная...

ПК>> Нет, я полагаюсь на систему, которая сгенерирует аппаратное исключение

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

V> А ты для какого рынка программы то пишешь?


Сейчас -- работаю в команде, пишущей движки для клиент-серверных бизнес-
приложений (свой orb, свой application server, аналог win fs, свой движок
форм и т.п.)

V> Действиетльно. Ну, тебе виднее. Правда дотнетные и явовские приложение

V> которые с этой твоей точкой зрения не согласны наботают все же надежнее,

Надежнее, чем что? Если, чем C++ (делая догадки по остальным сообщениям
в данной теме), то это просто неверно: они по определению не могут работать
надежнее, чем их виртуальные машины, которые как раз на C++ и написаны.

A>>> Ни разу не сталкивался. Вон янус в настоящий момент после любых

A>>> необработанных исключений в процессе работы продолжает жить.

ПК>> Вот на нем-то я как раз недавно и наблюдал типичный упомянутый

ПК>> глюкодром. Произошло как раз после исключения в ответ на разорвавшееся
ПК>> соединение во время синхронизации.

V> Паша, ты использовал Янус? А можно поглядеть на отправленные

V> тобой сообщения?

Вряд ли. Я периодически скачиваю новую версию, немного играюсь, в очередной
раз разочаровываюсь, и деинсталлирую. Т.е. прогресс, безусловно, наблюдается,
но как-то пока не торкает... А жаль. В него можно было бы вставить репликацию,
которой мне в News-клиентах не хватает.

V> Что-то мне не верится, в то что ты вообще его использовал. Янус как

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

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

Янус установлен в C:\Bin\RSDN\Janus. База лежала в
D:\Users\Pavel\private\internet\janus.

Пробуя воспроизвести предыдущую ошибку, потушил Янус и удалил содержимое
каталога D:\Users\Pavel\private\internet\janus, перезапустил Янус.

Он справедливо сказал, что файла D:\Users\Pavel\private\internet\janus\config.xml
нет, и выдал окошко "Новый пользователь". Вбил пользователя и пароль, и нажал
"ОК". Не заметил, что в поле каталога для базы почему-то оказалось значение
C:\Bin\RSDN\Janus\Pavel. Получил такую ошибку:

************** Exception Text **************
System.Data.OleDb.OleDbException: Could not find file 'D:\Users\Pavel\private\internet\janus\janus.mdb'.
at System.Data.OleDb.OleDbConnection.ProcessResults(Int32 hr)
at System.Data.OleDb.OleDbConnection.InitializeProvider()
at System.Data.OleDb.OleDbConnection.Open()
at Rsdn.Janus.DatabaseManager.SetVar(String varName, Object varValue)
at Rsdn.Janus.DBVars.SetVar(String name, Object val)
at Rsdn.Janus.LocalUser.CreateUser(String dbp, String uname, String pwd)
at Rsdn.Janus.OptionsUserForm.SaveUserInfo()
at Rsdn.Janus.OptionsUserForm.btnOk_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
<...>


Т.е. Янус решил, что база должна быть в D:\Users\Pavel\private\internet\janus,
а не в C:\Bin\RSDN\Janus\Pavel, где он же мне и предложил создать ее в диалоговом
окошке, хотя создал он ее таки в C:\Bin\RSDN\Janus\Pavel.

Удаляем все, и снова запускаем Янус. На этот раз, хотя в последний раз он
создал config.xml в D:\Users\Pavel\private\internet\janus, почему-то он говорит,
что не найден C:\Bin\RSDN\Janus\Pavel\config.xml. ОК. Появляется окошко "Новый
пользователь". Снова предлагает Вручную вбиваю правильный путь,
D:\Users\Pavel\private\internet\janus, имя и пароль, и жму ОК. Нет, не ОК:

************** Exception Text **************
System.IO.DirectoryNotFoundException: Could not find a part of the path "C:\Bin\RSDN\Janus\Pavel\config.xml".
at System.IO.__Error.WinIOError(Int32 errorCode, String str)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean useAsync,
String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode)
at Rsdn.Janus.Config.Save()
at Rsdn.Janus.LocalUser.CreateUser(String dbp, String uname, String pwd)
at Rsdn.Janus.OptionsUserForm.SaveUserInfo()
at Rsdn.Janus.OptionsUserForm.btnOk_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
<...>


В общем, пока не пробраузил кнопочкой "Обзор", ему не полегчало...

ПК>> После этого, даже когда соединение вернулось, ни одна синхронизация не

ПК>> проходила, сообщая что-то о вновь возникшем исключении.

V> Ладно, поверим тебе. Но скажи мне, что было бы если в момент

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

Все зависит от того, что произошло. Если нарушение предусловия (ошибка
программиста), то я предпочту аварийное завершение, естественно, с сохранением
редактируемого сообщения. Впрочем, так же как и при принудительном завершении
приложения через Task Manager или при "жестком" перезапуске компьютера. Например,
так делает Опера: даже при отключении питания после запуска я возвращаюсь в то
же состояние, что и перед прерыванием работы.

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

A>>> Пример таких приложений можно?


ПК>> См. выше.


V> Отмазка не удачная. Надо было Янус хотя бы попробвать.


Попробовал еще раз (см. выше). Пусть еще подрастет Предлагаю завязать с обсуждением
Януса. Я не хотел о нем говорить, но Андрей в очередной раз привел
Автор: AndrewVK
Дата: 19.07.05
его
в качестве примера особо надежного приложения, и я не удержался, о чем уже жалею.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[21]: Checked exceptions... зло или добро?
От: Павел Кузнецов  
Дата: 20.07.05 05:17
Оценка:
VladD2,

V> Специльно проверил твои слова. Запустил соеденение и быстренько выдернул

V> шнур. Как раз попал на закачку новых сообщений. <...>
V> Отвечаю тебе я тоже без перезапуска Януса. Так что не нужно придумывать
V> сказуи.

Дык, непредсказуемость есть непредсказуемость. Подобные ошибки тем и плохи,
что нерегулярны. У меня тоже воспроизвести не получилось. Когда воспроизводилось,
было четко видно, что соединение есть, все приложения работают, Янус тоже
наполовину работает, но где-то в процессе синхронизации обламывается. Немного
с другим сообщением (что-то о преждевременном конце gzip-стрима). И ошибку
в итоге какую-то странную выдавал, по-моему, даже без красного "крестика",
то ли треугольничком, то ли восклицательным знаком в облаке. После
перезапуска ему совершенно четко полегчало, и более он не чудил.

Хотел еще скриншот снять, но поленился.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[21]: Checked exceptions... зло или добро?
От: Павел Кузнецов  
Дата: 20.07.05 05:30
Оценка:
IT,

ПК>> соединение во время синхронизации. После этого, даже когда соединение

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

I> Твой пример скорее говорит о неотлаженности приложения, чем об устойчивости приложения.


Ну, как ни назови, в первоначальную картинку, обрисованную Андреем, не вписалось:

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

Хотя, жизнь, конечно, у всех разная
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[20]: Checked exceptions... зло или добро?
От: IT Россия linq2db.com
Дата: 20.07.05 05:32
Оценка: +2
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Это логическая ошибка. Другими словами, ошибка программиста. Для понимания "моей"

ПК>терминологии см., например, этот учебный курс:

ПК>

ПК>... Such errors should be corrected before the program is deployed.


Твоя терминология имеет смысл до тех пор пока какой-нибудь баг не ушёл в продакшин, после этого всем уже всё равно как его называть.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[18]: Checked exceptions... зло или добро?
От: IT Россия linq2db.com
Дата: 20.07.05 05:48
Оценка: +1
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>NullReferenceException — типичная логическая ошибка. Внешнему коду доверять странно, если он передал нулевую ссылку там, где этого делать нельзя. Соответственно, надеяться на то, что внешний код корректно "восстановится", тоже не приходится: он уже находится в каком-то невалидном состоянии, на которое не рассчитывали при его разработке. Попытка "восстановления" после подобной ошибки зачастую приводит к попаданию в нормальный поток исполнения с нарушенными инвариантами, после чего приложение скорее не работает, чем работает.


Типичная проблема stateful подхода.

ПК> Т.е., в случае управляемых сред, оно при этом обычно не "падает", но это даже хуже, т.к. у пользователя создается иллюзия исправной работы, в то время, как "внутри" уже самый настоящий глюкодром. Это очень легко наблюдать на многих приложениях, написанных на Java и C# в случаях возникновения непредусмотренных исключительных ситуаций. Т.к. чтоб работать в случае нарушенных инвариантов, нужно проверять все на свете, что, очевидно, сделать невозможно.


Используй stateless и будет тебе шастя.

ПК>Вообще же, в более строгих случаях, для приложений с критическими требованиями, попытки продолжения работы после диагностирования логической ошибки традиционно недопустимы: в таком состоянии приложение должно максимально коротким путем завершить свою работу, при необходимости сохранив текущие данные.


Испорченные данные?

ПК>Далее, в случае серверного приложения -- задача watch dog сохранить crash dump, log файл и т.п., и перезапустить приложение.


Ерунда. Влад тебе уже рассказал про десктопы. В случае серверных приложение это тем более неверно. Серверный (да даже просто бизнес код) вообще не должен обрабатывать никаких исключений. Разве что только для логирования, да и то я бы это обсудил. Исключение из бизнес кода должно сквозняком улетать пользователю в первозданном виде. Сервер не должен пытаться его каким-то волшебным образом обработать. Это не его (простите мне мой французский) собачье дело. Не справился с поставленной задачей — доложи тому кто тебя тебе эту задачу поручил.

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

ПК>В частности, приводится вполне наглядный пример диагностики в системе автоматического пилотирования отрицательной высоты.


Мне было бы очень интересно ознакомиться с методикой обеспечения надёжности в таких системах, но никак не с попыткой обобщения данной предметной области на все виды программного обеспечения.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[21]: Checked exceptions... зло или добро?
От: Павел Кузнецов  
Дата: 20.07.05 05:50
Оценка:
IT,

ПК>>

ПК>> ... Such errors should be corrected before the program is deployed.


I> Твоя терминология имеет смысл до тех пор пока какой-нибудь баг не ушёл в

I> продакшин, после этого всем уже всё равно как его называть.

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

Если же подобные баги приводят к прерыванию исполнения, у такого бага все
шансы стать гвоздем в заднице службы поддержки. Но, по крайней мере, его
ловить будет легче, и вредить он будет только локально. Если, конечно,
приложение надежно (умеет не терять данные при всевозможных сбоях, и не
только программных).
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[22]: Checked exceptions... зло или добро?
От: IT Россия linq2db.com
Дата: 20.07.05 05:59
Оценка: +1
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Ну, как ни назови, в первоначальную картинку, обрисованную Андреем, не вписалось:

ПК>

ПК>Вон янус в настоящий момент после любых необработанных исключений в процессе работы продолжает жить.


Могу это ещё раз подтвердить. Янус, конечно, не самая безглючная программа. Но учитывая то, что это, с самого рождения, по совместительству полигон для удачных и не очень идей, boy scout camp, ну и чуть чуть читалка форумов, то рузультат можно признать вполне удовлетворительным. Не думаю, что любая похожая C++ софтинка выдержала бы подобные издевательства.

ПК>Хотя, жизнь, конечно, у всех разная


Между прочим, твоя жизнь (в том же самом смысле) тоже зависит от кода написанного на C#. Не забыл ещё через что ты сам читаешь RSDN и на чём написан RSDN NNTP Server?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[22]: Checked exceptions... зло или добро?
От: IT Россия linq2db.com
Дата: 20.07.05 06:06
Оценка: 2 (1) +2 :)
Здравствуйте, Павел Кузнецов, Вы писали:

I>> Твоя терминология имеет смысл до тех пор пока какой-нибудь баг не ушёл в

I>> продакшин, после этого всем уже всё равно как его называть.

ПК>Не вполне: исключительная ситуация остается исключительной ситуацией, а баг остается багом.


Тогда мне интересно твое определение исключительной ситуации для простого деревенского парня. А то вот это мне как-то не совсем по силам

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


Что же такое исключительная ситуация?

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


Паша, читай более подробно о stateless. Правильные stateless приложения не теряют данные, т.к. им нечего терять.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[22]: Checked exceptions... зло или добро?
От: Павел Кузнецов  
Дата: 20.07.05 06:12
Оценка:
IT,

I> Ты забыл спросить о версии януса, которую когда-то использовал Паша


Запустил еще раз (пришлось опять проделать танцы с бубном, описанные
в соседнем сообщении, т.к. базу уже снес ).

Версия 1.1.4 beta 7 ревизия 501
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[21]: Checked exceptions... зло или добро?
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 20.07.05 06:20
Оценка:
VD> Янус как раз при проблемах со связью умудряется работать даже когда к серверу нельзя пробиться из броузера или через почту.

И умудряется не работать при отсутсвии оных проблем. Как это было в понедельник.
... << RSDN@Home 1.1.4 stable rev. 510>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[19]: Checked exceptions... зло или добро?
От: Павел Кузнецов  
Дата: 20.07.05 06:37
Оценка:
IT,

ПК>> Попытка "восстановления" после подобной ошибки зачастую приводит к

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

I> Типичная проблема stateful подхода.


Ну, stateless далеко не универсален. Посмотрел бы я на stateless компилятор
или stateless графический редактор...

ПК>> приложение должно максимально коротким путем завершить свою работу,

ПК>> при необходимости сохранив текущие данные.

I> Испорченные данные?


Нет, конечно, для этого должна быть максимально ранняя диагностика. Плюс должны
автосохраняться несколько версий. Собственно, тот же Word так и делает...

ПК>> Далее, в случае серверного приложения -- задача watch dog сохранить

ПК>> crash dump, log файл и т.п., и перезапустить приложение.

I> Ерунда. Влад тебе уже рассказал про десктопы. В случае серверных

I> приложение это тем более неверно.Серверный (да даже просто бизнес код)
I> вообще не должен обрабатывать никаких исключений.

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

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

I> Другими словами — контекст вызова умирает вместе с вызовом и никаким

I> существенным образом на работоспособность сервера это влиять не должно
I> ни при удачном, ни при не очень исходе.

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

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

То же самое касается и той же виртуальной машины C# или Java. Если она в себе
обнаружит нарушение предусловий, уверен, никаких исключений при этом не будет.
Да и что может сделать клиент в подобной ситуации?.. Нажать "Continue"?

Да чего тут гадать, вот пример (специально пришлось поискать функцию, в которой
и предусловия проверяются, и бросается что-нибудь):
void OleVariant::MarshalOleRefVariantForObject(OBJECTREF *pObj, VARIANT *pOle)
{
    THROWSCOMPLUSEXCEPTION();

    _ASSERTE(pObj != NULL && pOle != NULL && V_VT(pOle) & VT_BYREF);

<...>
               // If the variant types are still not the same then call VariantChangeType to
                // try and coerse them.
                if (V_VT(&vtmp) != vt)
                {
                    COMPlusThrow(kInvalidCastException, IDS_EE_CANNOT_COERCE_BYREF_VARIANT);
                }
                else
                {
                    InsertContentsIntoByrefVariant(&vtmp, pOle);
                }
            }
            GCPROTECT_END_VARIANTDATA();
        }
 }
}

Предусловия классически диагностируются с помощью assert. Отклонения входных данных,
не нарушающие предусловия, сообщаются клиенту с помощью исключений. Все по науке

Но вот с чем можно легко согласиться, так это с тем, что, безусловно, грань между
исключениями и ошибками не так уж ясна заранее, до анализа конкретной ситуации.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[16]: Checked exceptions... зло или добро?
От: alexeiz  
Дата: 20.07.05 06:51
Оценка: 1 (1)
"Cyberax" <37054@users.rsdn.ru> wrote in message
news:1278475@news.rsdn.ru
> mishaa wrote:
>
>>> В С++ мне жутко нравится механизм nothrow. Вот скрестить бы его с
>> Java....
>> nothrow — это Вы про __declspec
>> <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_langref_nothrow.asp&gt;
>>
>
> Это я про "throw()" — обозначение того, что функция не будет кидать
> никакие исключения.
>
>> А зачем он в Java? Указать что и unchecked exeptions не проходят?
>> Дык, а толку то. Может в C#-пе будет полезен.
>
> В Яве/C# исключение может вылететь в любой момент (какой-нибудь
> OutOfMemory), а в С++ можно гарантировать, что функции не кинут
> исключения.

В Whidbey .NET для этой цели были введены Constrained Execution Regions (CER) (http://blogs.msdn.com/bclteam/archive/2005/06/14/429181.aspx). В пределах CER (почти) не могут произойти асинхронные исключения (можно, конечно, специально постараться, но тогда сам виноват). Таким образом облегчается управление unmanaged ресурсами в managed коде. Хотя следует отметить, что CER обходятся не дёшево.

Такие проблемы в .NET по большому счету существуют именно из-за того, что в нём скрестили синхронные и асинхронные исключения и принебрегли тем фактом, что это фундаментально разные типы исключений, и в их обработке применяются фундаментально разные подходы. Вследствии этого уже никакого no-throw guarantee быть не может, да и код, который дает даже basic guarantee писать нетривиально (хотя с CER, наверное, возможно, но опять-же это требует дополнительных затрат в runtime).
Posted via RSDN NNTP Server 1.9
Re[22]: Checked exceptions... зло или добро?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.07.05 07:03
Оценка: 130 (8) +1
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Сначала я хотел бы остановиться на самой ситуации. В данном случае лучше было

ПК>тем или иным образом сделать потенциальное отсутствие возвращаемого значения
ПК>явным. Скажем, так:
ПК>
ПК>boost::optional<std::string>
ПК>find_user_group_name( std::string const& user_name, security_data_t );
ПК>

ПК>в таком случае данная ошибка была бы поймана вовремя. А именно, во время
ПК>написания/модификации кода/интерфейса, т.к. пользователь физически не смог
ПК>бы пропустить факт потенциального отсутствия возвращаемого значения.

ПК>Но допустим, что интерфейс именно такой, как он обозначен ранее...


Применительно к const char * значение 0 является таким же валидным значением, как и, например, "root" или "wheel". Проблема в другом: в том, что среди множества корректных возвращаемых значений есть подмножество, которое нельзя использовать в каком-то конкретном контексте. Скажем при обращении к do_something.

e>> Итак, что в такой ситуации лучше делать? Позволить приложению время от

e>> времени падать с crush dump-ом или порождать исключение в надежде, что
e>> на каком-то уровне его смогут обработать и выполнить мягкий рестарт?

ПК>Основная проблема в такой логике заключается в том, что от "мягкого" рестарта

ПК>ничего не изменится, т.к. невалидное состояние приложения вызвана его логикой,
ПК>а не какими-то внешними данными, которые могут прийти в другое состояние.

ПК>Хуже того, т.к. мы сообщаем об ошибке средствами, предназначенными для обработки

ПК>ситуаций, предусмотренных логикой приложения, мы рискуем вообще "проглотить"
ПК>эту ошибку, и продолжить исполнение в невалидном состоянии.

Вот здесь уже начинается момент, который мне не нравится. Термин "невалидное состояние" слишком общ и туманен. Для каждого конкретного приложения, более того, для каждого отдельного фрагмента приложения, "невалидность" может иметь совершенно разный смысл.

ПК>Если можно быть уверенным в изоляции состояния, ассоциированного с потоком

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

ПК>Соответственно, если считать, что ошибки в каких-то фрагментах приложения

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

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

ПК>Примерами могут служить плагины, множественные сессии исполнения в серверах

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

ПК>Но, имхо, рапортовать нарушение предусловия плагину в виде исключения совершенно

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

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

e>> Имхо, в случаях, когда возможна проверка на заведомо некорректные

e>> параметры (как правило, это public интерфейс какого-либо класса,
e>> библиотеки или модуля), лучше все-таки порождать исключения. Во-первых,
e>> потому, что это самая ближайшая к месту появления проблемы точка
e>> (все-таки гораздо понятнее, когда в исключении будет сказано, что это
e>> do_something и причина в нулевом значении p). А то ведь crush dump мог
e>> быть инициирован где-нибудь на три уровня вложенности ниже. А еще хуже,
e>> что он мог быть вообще не инициирован, если в текущем состоянии
e>> программы параметр p игнорируется.

ПК>В общем случае речь не идет об игнорировании нарушения предусловий. Напротив,

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

e>> Во-вторых, потому, что это дает возможность приложению, если оно

e>> спроектировано на восстановление после подобных исключений, восстановиться
e>> на каком-то уровне.

ПК>Т.е. ты предлагаешь закладывать в поток исполнения логику, рассчитанную на

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

ПК>Вместо этого придумали понятия инвариантов, предусловий, постусловий и т.п.

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

Нет, моя идея в другом (причем это не моя идея, я ее откуда-то давным-давно позаимствовал).
Вот пусть у нас есть объект B у которого есть публичные методы. Публичные методы B должны проводить диагностику заведомо некорректных параметров. Поскольку для B работа с некорректными параметрами является такой же исключительной ситуацией, как например, исчерпание свободного места на диске или невозможность подключения к удаленной БД. И B может сразу отказаться от продолжения работы путем порождения исключения. При этом состояние B остается валидным (т.к. ничего деструктивного он не совершил).

e>> Ну например,

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

ПК>В таком случае подобная ситуация не является нарушением инвариантов сервера,

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

ПК>Но вот если, например, в коде, диспетчеризующем сессии, т.е. не обладающем

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

Именно так. Но я думаю ты с этим согласен, неразумно выпускать исключение из контекста сессии в контекст диспетчера сессий, если сам контекст сессии в состоянии с этой ситуацией справится. Причем сложность здесь в том, что контекст сессии может даже не знать, что за исключение, где и почему оно возникло. Я бы здесь сделал так: контекст сессии ловит все исключения, пытается откатить все транзакции (в общем смысле, не обязательно это транзакции в БД) и перейти в какое-то начальное/конечное состояние. Если за время такого отката исключений больше нет, то сессия обычным образом завершается (может быть с необходимым логированием, выдачей тревог, отсылкой e-mail и пр.). Но если и в процессе отката возникает исключение, то дело совсем плохо. Вот тут контекст сессии должен прекратить свои попытки и отдать исключение (возможно странслированное) наружу. Но при этом и контекст сессии должен обеспечить базовую гарантию (т.е. отсутствие утечек ресурсов и возможность корректного удаления). А диспетчер сессий пойдет таким же путем -- сначала попробует разобраться с ситуацией сам (прибив сбойную сессию). Если и у него возникнут непредвиденные проблемы, то пусть он их еще выше передает. Но так же обеспечивая базовую гарантию.

И так на каждом уровне абстракции.

e>> Попробую резюмировать. Имхо, существует целый класс ошибок -- заведомо

e>> неверные аргументы для public-интерфейсных функций/методов. Бороться с
e>> такими ошибками, имхо, как раз удобнее выбрасывая исключения на самом
e>> раннем этапе. Поскольку есть большая вероятность, что нарушение
e>> предусловий (т.е. некорректность аргумента) вызвано не жесткими сбоями в
e>> коде (повисшие/битые указатели или что-либо подобное), а элементарными
e>> алгоритмическими ошибками или невнимательностью программиста.

ПК>Гм... А какая разница, какими ошибками вызвано нарушение предусловий?

ПК>Все равно нужно завершать поток исполнения, в котором диагностирована
ПК>ошибка. Согласен, что следует это делать как можно раньше, по возможности
ПК>не дожидаясь низкоуровневых/аппаратных сигналов/исключений.

Я думаю, что разница есть и она важна. Если ошибка вызвана битым/повисшим указателем, то бесполезно пытаться сделать что-то осмысленное. Не понятно, что еще разрушено и не сделаем ли мы хуже, если продолжим работу. Но если ошибка вызвана некорректными входными данными, то лучше эти данные отвергнуть. В том числе и посредством исключения.

Кроме того, мы как-то неявно подразумеваем, что некорректные входные данные (частный случай нарушения предусловий) будут приводить к краху приложения (поэтому мы и приводим в примерах нулевые указатели). Но ведь могут быть и другие последствия. Например, в итерационный метод решения СЛАУ могут передать слишком маленькое значение погрешности (скажем 0.00001 вместо 0.0001). Из-за чего итерация будет сходится, но на несколько порядков дольше. Нарушение предусловия здесь явное, но никакого сбоя не будет -- будет слишком медленная работа.

e>> Паша, может как раз такие вещи ты и называл в числе тех редких случаев,

e>> когда после ошибки в программе восстановление еще возможно?

ПК>Я подразумевал случаи, когда контекст исполнения изолирован.


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

Что мне еще не понравилось в обсуждении в с++.moderated, так это то, что там чуствуется некая вера в то, что программы могут быть полностью отлаженными. И если появляется какая-то ошибка (некорректные аргументы для метода), то это от недостаточности тестирования. Поэтому вместо продолжения работы лучше с фанфарами грохнуться в core dump. Это напоминает веру в то, что статическая типизация или достаточное unit/regression/integration-тестирование способно повысить качество ПО. Имхо, сложность в том, что ошибки есть и будут в отлаженных программах всегда. И что кроме повышения объема и качества тестирования до запуска приложения в эксплуатацию нужно еще заботится о том, чтобы программа была способна выживать в условиях проявления необнаруженных ранее ошибок (об этом речь заходила в Re[23]: Что толку в Ада если Ариан 5 все равно упал
Автор: А почему вы спрашиваете
Дата: 22.06.05
):

Очень интересно, что все участники дискуссии полностью проигнорировали этот фрагмент отчета. Собственно, ничего удивительного в этом нет, это типичное заблуждение, которое заключается в том, что ПО можно сделать свободным от дефектов и предусматривать какие-то меры восстановления от программных сбоев нет необходимости. И это-то при том, что именно программные ошибки занимают второе место среди причин отказов информационных систем (первое место — cockpit failure), а аппаратные сбои только на третьем.

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

Ссылка по теме: диссертация Joe Armstrong'а на тему "Making reliable distributed systems in the presence of software errors" (http://www.sics.se/~joe/thesis/armstrong_thesis_2003.pdf)


Если проводить аналогию с живыми организмами, то сваливание в core dump при обнаружении нарушения предусловия напоминает насильственное лишение жизни после ампутации конечности. Хотя жизнь показывает, то даже с очень большим числом повреждений организм вполне способен жить.
... << RSDN@Home 1.1.4 stable rev. 510>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[20]: Checked exceptions... зло или добро?
От: alexeiz  
Дата: 20.07.05 07:11
Оценка: +2
"Павел Кузнецов" <5834@users.rsdn.ru> wrote in message
news:1278839@news.rsdn.ru
> eao197,
>
> e> Мне интересно, как в C++ можно гарантировать, что функция не кинет
> исключения?
>
> Спецификация throw() подходит к этому ближе всего: в случае
> исключения исполнение программы будет прервано.

По стандарту это так. Однако, не все компиляторы поддерживают спецификации исключений. И те, что не поддерживают, могут сделать совсем противоположную вещь, а именно использовать throw(), как гарантию от программиста, что данная функция не будет бросать, и генерировать оптимизированный код, который вообще не предусматривает обработку исключений, раскрутку стека и вызов деструкторов. Именно так ведет себя Visual C++ (throw() is equivalent to __declspec(nothrow)).

Такое поведение imo является единственно полезным применением спецификаций исключений в C++.
Posted via RSDN NNTP Server 1.9
Re[23]: Checked exceptions... зло или добро?
От: Павел Кузнецов  
Дата: 20.07.05 07:24
Оценка: 1 (1)
eao197,

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

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

e> Кроме того, мы как-то неявно подразумеваем, что некорректные входные

e> данные (частный случай нарушения предусловий) будут приводить к краху

Некорректные входные данные не есть частный случай нарушения предусловий.

e> приложения (поэтому мы и приводим в примерах нулевые указатели). Но ведь

e> могут быть и другие последствия. Например, в итерационный метод решения
e> СЛАУ могут передать слишком маленькое значение погрешности (скажем
e> 0.00001 вместо 0.0001). Из-за чего итерация будет сходится, но на
e> несколько порядков дольше. Нарушение предусловия здесь явное, но
e> никакого сбоя не будет -- будет слишком медленная работа.

Это пример неудачных (даже не некорректных данных), но никак не нарушение
предусловия. Хотя, конечно, грань не так уж точна, но ее всегда можно
определить для заданного приложения, пусть и не универсально.

e> Что мне еще не понравилось в обсуждении в с++.moderated, так это то, что

e> там чуствуется некая вера в то, что программы могут быть полностью
e> отлаженными. И если появляется какая-то ошибка (некорректные аргументы
e> для метода), то это от недостаточности тестирования. Поэтому вместо
e> продолжения работы лучше с фанфарами грохнуться в core dump. Это

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

Еще одна ссылка:
http://www.cs.usfca.edu/~parrt/course/601/lectures/programming.by.contract.html

Failure

Asserts and "by contract" specifications catch programmer errors not run-time
errors! They catch invalid or unknown state problems caused by programming errors.
Do not attempt to recover from assert failures. You are "out of known space."

Don't use asserts for runtime problems such as:
"can't find file"
invalid web site page arg
input arg "rate" too fast

In these cases, you should throw InvalidArgumentException or whatever. The system can
continue to operate in this case.

Asserts/conditions can be taken out after development, but you need input checks always.

What does it mean when contract fails?
If preconditions met, supplier guarantees postconditions.
Failure of precondition implies problem with client.
If postcondition fails, it's a bug in supplier.

Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[20]: Checked exceptions... зло или добро?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.07.05 07:29
Оценка: +1
Здравствуйте, Павел Кузнецов, Вы писали:

A>> Гарантии нет, а без гарантии мало что построить можно.


ПК>Отчего же?


От того, что, с точки зрения пользователя, вылетает сервер каждый раз или через раз разница небольшая.

ПК>>> NullReferenceException — типичная логическая ошибка.


A>> Это может быть совершенно произвольная ошибка.


ПК>Например?


Приведу, если скажешь что ты подразумеваешь под логической ошибкой.

A>> Ты в своих программах всегда проверяешь все параметры на null? А если он

A>> таки null, что делаешь?

ПК>Нет, я полагаюсь на систему, которая сгенерирует аппаратное исключение в ответ на разыменование

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

И чем это круче NullReferenceException?

ПК>С точки зрения устойчивости приложения некорректно порождать исключение при обнаружении

ПК>логической ошибки.

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

ПК> Нужно обеспечивать внешние резервные средства, и исправлять ошибку,

ПК>а не маскировать ее исключениями.

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

A>> Ни разу не сталкивался. Вон янус в настоящий момент после любых

A>> необработанных исключений в процессе работы продолжает жить.

ПК>Вот на нем-то я как раз недавно и наблюдал типичный упомянутый глюкодром. Произошло

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

Первый раз о таком слышу. Надеюсь ты поверишь в то, что опыт использования сего продукта у меня обширный?
... << RSDN@Home 1.2.0 alpha rev. 580>>
AVK Blog
Re[14]: Checked exceptions... зло или добро?
От: alexeiz  
Дата: 20.07.05 07:34
Оценка: +1
"VladD2" <73@users.rsdn.ru> wrote in message news:1279390@news.rsdn.ru
> Здравствуйте, Павел Кузнецов, Вы писали:
>
>> Из деструкторов, равно как и из всяких Finalize и Dispose,
>> исключения выпускать не рекомендуется.
>
> Ну, из Dispose это неприятно но не смертельно. Да и суть Dispose-ов
> все же неуправляемые ресурсы освобождать. По сему писать их часто не
> приходится и проблем особых не возникает. А с деструкторами согласен.

Не смертельно в смысле того, что runtime сможет продолжить выполнение программы. Однако с точки зрения надёжности выброс из Dispose имеет тот-же эффект, что и выброс из деструктора в C++. Гарантировать сохранение инвариантов, освобождение ресурсов и нормальную обработку исключений в таком случае невозможно.

PS: Напомню, что в C++/CLI деструкторы прямо эквивалентны Dispose(), и Visual C++ по крайней мере в Beta2 генерирует такой код для деструкторов, который в критических случаях просто проглатывает любые исключения, из него выбрасываемые.
Posted via RSDN NNTP Server 1.9
Re[22]: Checked exceptions... зло или добро?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.07.05 07:40
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Надежнее, чем что? Если, чем C++ (делая догадки по остальным сообщениям

ПК>в данной теме), то это просто неверно: они по определению не могут работать
ПК>надежнее, чем их виртуальные машины, которые как раз на C++ и написаны.

Это было бы верно, если бы в отладку каждого приложения на С++ вкладывали столько же, сколько в отладку CLR.

ПК>Вряд ли. Я периодически скачиваю новую версию, немного играюсь, в очередной

ПК>раз разочаровываюсь, и деинсталлирую. Т.е. прогресс, безусловно, наблюдается,
ПК>но как-то пока не торкает... А жаль.

Да, сильна

ПК>В него можно было бы вставить репликацию,

ПК>которой мне в News-клиентах не хватает.

Репликацию чего и куда?
... << RSDN@Home 1.2.0 alpha rev. 580>>
AVK Blog
Re[23]: Checked exceptions... зло или добро?
От: Павел Кузнецов  
Дата: 20.07.05 07:47
Оценка:
AndrewVK,

ПК>> Надежнее, чем что? Если, чем C++ (делая догадки по остальным

ПК>> сообщениям в данной теме), то это просто неверно: они по определению
ПК>> не могут работать надежнее, чем их виртуальные машины, которые как раз
ПК>> на C++ и написаны.

A> Это было бы верно, если бы в отладку каждого приложения на С++

A> вкладывали столько же, сколько в отладку CLR.

Дык, не отладкой единой. При определенном подходе отладка в C++ нужна никак
не больше, чем в C#/Java, т.к. средств для организации статических проверок больше.

ПК>> В него можно было бы вставить репликацию, которой мне в News-клиентах не хватает.


A> Репликацию чего и куда?


Данных между несколькими разными базами. Скажем, на работе, дома на десктопе, и на лаптопе.
Больше всего напрягает рутинно помечать сообщения, прочитанные на одной из машин, как
прочитанные на других машинах.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[24]: Checked exceptions... зло или добро?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.07.05 09:23
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Дык, не отладкой единой. При определенном подходе отладка в C++ нужна никак

ПК>не больше, чем в C#/Java, т.к. средств для организации статических проверок больше.

Это не важно. Важно то что сравнивать надежность прикладных программ с надежностью CLR некорректно.

ПК>>> В него можно было бы вставить репликацию, которой мне в News-клиентах не хватает.


A>> Репликацию чего и куда?


ПК>Данных между несколькими разными базами. Скажем, на работе, дома на десктопе, и на лаптопе.

ПК>Больше всего напрягает рутинно помечать сообщения, прочитанные на одной из машин, как
ПК>прочитанные на других машинах.

Я обхожусь перетаскиванием БД.
... << RSDN@Home 1.2.0 alpha rev. 580>>
AVK Blog
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.