Здравствуйте, Кодт, Вы писали: К>Есть ряд макросов, словесно описывающих суть ассерта — PRECONDITION, POSTCONDITION, ASSERTION общего назначения. К>Они проверяют условия и в случае облома К>- проходят через контрольную точку (где можно остановиться для отладки) К>- кидают специальное исключение, которое К>- — при размотке стека пишет в журнал, в каких функциях произошёл отстрел К>- — ловится в самой нижней функции потока, откуда принимается решение остановить работу, перезапустить и т.д.
У меня что-то похожее, только логика настраеваемая через установку хендлеров. Тобишь если в конкретном приложении нужна специальная логика (например стек можно более продвинуто оттрейсить) можно установить свой обработчик. Только вот исключения я в ассертах не кидаю.
Ну и ассёрты называются REQUIRE, VIOLATION, EMERGANCY. Плюс REQUIRE и VIOLATION бывают трёх видов. Обычные — из кода впринципе не удаляюся. DBG_* — проверяются только для отладочной версии, и STRICT_* — обычно включены для тестов независимо от того дебажная сборка или нет. Ещё есть WARNING, тоже бывает полезным, но очень редко. WARNING — это как вроде бы и не должно так быть, но с другой стороны и к сбою это не приведёт.
Смысл неудаляемых ассёртов в отлове фатальных сбоев невыявленных в процессе тестирования или последствий ошибок второго рода. В релизе помогает сгенерить крашдамп позволяющий составить представление о ситуации в которой произошл сбой.
И надо заметить, до того момента пока я не уверен что REQUIRE или VIOLATION тормозит код, переводить его в удаляемый STRICT_* я не буду. Себе дороже выйдет. DBG_* версии используются именно для отладки проблемных участков ибо отрабатывают только в отладочном коде.
Ещё очень важный момент, который как-то скипают люди пренебрегающие ассертами. Ассерты предназначены для отлова ошибок кодирования. Ситуаций которых в коде быть вообще не может и если такая ситуация произошла, то это уже всё, финиш. И если мы говорим о библиотеках то в них это необязательно ошибка алгоритма, но так же и нарушение контракта. Просто вопрос в жёсткасти реакции. Но моё имхо, что если некое поведение не предусмотренно программой, то дальнейшее её исполнение должно быть прервано. Уходм в отладчик или посылкой багрепорта, не суть важно. Важно что дальнейшее поведение программы непредсказуемо. Для отлова таких ситуаций и служат ассёрты.
minorlogic wrote:
> А>Почему в большинстве библиотек которые я видел очень редко > используются assert'ы? > А>Типа "настоящие" программисты ошибок не совершают... > Да нет , асерты используются на полную при разработке и отладке , а > уже из отлаженных кусков кода обычно удалаяютяс.
Ассерты никогда, я повторяю НИКОГДА, не надо удалять из кода. Можно
отключать макросами (типа MYMODULE_NOASSERT) и, естественно, их надо
выключать в релизе. Но они всегда должны оставаться в коде.
Кстати, у ассертов под MSVC есть еще одно интересное применение:
Alxndr wrote: > A>>Можешь привести пример, когда полный code coverage действительно > очень сложен? > ME>Не могу ни вспомнить, ни придумать > Еще вопрос: если мы имеем полный code coverage — нафига нам вообще нужны > assert'ы?
Для проверки что код не только покрыт, но еще и работает.
Здравствуйте, Аноним, Вы писали:
А>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>Типа "настоящие" программисты ошибок не совершают...
Потому что assert — это самое убогое средство отладки, какое можно придумать.
В дебаг-версии он выводит assertion failed и убивает задачу по abort. В релиз-версии не вычисляет аргумент (повод для ошибок, когда важная функциональность случайно внесена внутрь assert-выражения).
Здравствуйте, Сергей Мухин, Вы писали:
СМ>дык одно дело библиотека, другое приложение. Вот пример библиотечной ф-ии
СМ>double sqrt( double X ) {
СМ>assert( X >= 0.0 );
СМ>// тра-тата
СМ>}
СМ>или
СМ>double sqrt( double X ) {
СМ>if( X < 0.0 ) throw ....
СМ>// тра-тата
СМ>}
СМ>что лучше для библиотеки?
Дело вкуса. Если я пишу в документации “X shall be a non-negative number”, то имею право при нарушении условия (а) бросать исключение, (б) выдавать неправильный ответ, (в) уходить в бесконечный цикл, (г) форматировать винчестер. Если я пишу в документации “if X is negative, throws std::domain_error”, то должен сделать проверку и бросить исключение.
С другой стороны — в C++ принято не платить за то, что не нужно. Поэтому клиент ожидает, что библиотечная функция не будет тратить время на проверку условия, которое, как он знает, всегда истинно. По крайней мере в релизе с оптимизацией.
C>>То есть assert'ы не просто удаляются из кода, а превращаются в хинты C>>компилятору.
А>А можно про это поподробнее, почему это лучше чем ((void)0) в релизе вместо ассерта?
The __assume keyword passes a hint to the optimizer. The optimizer assumes that the condition represented by expression is true at the point where the keyword appears and remains true until expression is altered (for example, by assignment to a variable). Selective use of hints passed to the optimizer by __assume can improve optimization.
Здравствуйте, Аноним, Вы писали:
А>ASSERT — это фича только для разработчиков кода, а не для юзера. Ассертами я проверяю самого себя во время работы над проектом, а юзера я проверяю непосредственно при вводе им значений, например если в edit'е введено неверное значение, всплывает диалог, типа "Попробуйте еще раз...".
А>Все реальные входные данные, естественно проверяются и в debug, и в release, потому что это данные поступающие от пользователя, т.к. входные.
А>Может я путано объяснил... но, если кратко, ассерты — это инструмент для разработчика. Для данных поступающих в программу от пользователя используются другие методы проверки: обычные условия, с выводом сообщения при отрицательном результате или выбросом исключения или еще что-то
Помимо всего прочего, assert — это еще и средство документирования кода, так как показывает инварианты в алгоритме.
Здравствуйте, <Аноним>, Вы писали:
А>Что за бред удалять асерты??? Они же в релизе и так не срабатывают. А>Ну, и про инварианты тут выше поветке правильно сказали.
Это не бред , а реалии. Еще раз повторяю многие программисты из отлаженного кода удаляют ассерты , возможно чтобы не загромождать код.
Сча ! Не могу терпеть , расскажу историю которая со мной реально приключилась.
Код который находится в разработке (много чужого не до конца понятного) все в жутком овральном режиме с требованиями чтобы только заработало , плюс жесткие требования к коду , ни одного лишнего движения которое бы моголо облегчить программирование , не чистка , не рефакторинг , вообще ничего.
В этих условиях я ставлю асерты чере каждые пару строк , хотя бы для того чтобы разобраться в работе алгоритмов.
Заказчику отдается промежуточный код и он с ним что то делает (видимо тестирует).
И ВОТ: От заказчика приходит требование "убрать все асерты и асертоподобные макросы из кода" , аргументируется это примерно так
"Как я могу быть уверен что код работет , если он может выдавать асерты ??? "
Я неделю после этого ходил согнутый , но ничего пришлось вычистить все асерты , и главное код "конечно заработал без багов".
Вот такой вот глубокий маразм встречается на белом свете.
pavel_turbin wrote:
> ssi>Это почему еще не имеет смысла ассертить свой код? > ssi>Думаю Вам следует прочитать серию статей Александреску про > assert'ы и enforcement'ы в C/C++ Users Journal. > это все так красиво выглядит теории. На практике, когда необходимо > достичь определеного качества кода за заданных промежуток времени, > чем-то приходиться пренебрегать.
Неправильная практика. У меня лично ассерты многократно окупаются на
времени отладки. Ну а их расстановка почти ничего не стоит по времени
(пару лишних клавиш нажать во время написания кода).
omka wrote: > C>Поэтому лучше всего в такой ситуации записать core dump и не делать вид, > C>что ничего не случилось. > Ну, механизм исключений делался не для того, чтобы делать вид, что > ничего не случилось — а локализовать место возникновения ошибки для > принятия решения о дальнейшей ходе работы.
Вот тебе пример:
void aVeryBadFunction()
{
char arr[10];
for(int f=0;f<20;++f)
arr[10-f-1]=f;
}
void goodFunction()
{
std::string aString;
aString="adfjnaksd";
aVeryBadFunction();
//Приплыли. Такой вот код может дать AE:for(size_t f=0;f<aString.size();++f)
aString[f]=toupper(aString[f]);
}
Все. Стэк разрушен, программа работать будет в зависимости от фазы Луны.
При попытке кинуть исключение мы только все ухудшим.
Называется это "нарушение инвариантов".
> В подобном случае именно в точке возникновения ошибки видно, что > дальнейшая работа приложения недопустима — не зачем генерировать > исключение — это верно.
Точка возникновения ошибки и точка срабатывания assert'а — это обычно
совершенно разные вещи.
> "На счет применения assert при сдаче в release — считаю, что всегда > нужно корректно завершать работу приложения" — может core dump это как > раз и есть корректное завершение работы — для системы и самого > приложения завершение приложения — самый безопасный выход.
code dump — это в любом случае аварийное завершение. "assert" в релизах
как раз противопоказан — так как часто в разы уменьшает быстродействие.
Здравствуйте, Сергей Мухин, Вы писали:
А>>Assert нужен разработчику кода, использующему данную библиотеку, на тот случай если он где-то забыл проверить данные поступившие от пользователя.
СМ>данные поступившие от пользоватля, надо проверять логикой (т.е. if), а ассерты то есть, то нет (в release). СМ>аналогично в библиотеке, вам дают ф-ию, и говорят, "вот ее поведение, оно отлично от при разных режимах компиляции" и такое терпеть?
В таких случаях говорят: "поведение при аргументах, нарушающих контракт (предусловие), не определено"; а как именно оно не определено (расстрел памяти или отладочное прерывание) — дело хозяйское.
Предпочтительно, конечно, отладочное прерывание.
Но если пользователь зарубится на это, и сделает тандем из специального обработчика прерывания (который будет, скажем, бросать исключение) и ловца, и пользоваться этим — то не пошёл бы такой пользователь куда подальше.
set_assertion_handler(throw_oops);
try
{
for(int n=0; ; ++n) // а пёс его знает, до скольки там надо считать
direct_access_to_nth_item(n);
}
catch(oops) // типа, конец цикла
{
}
Пример — STL-ные алгоритмы. Они не контролируют выход итераторов за границы, отдавая эту миссию пользователю.
Но могут помочь ему в отладке, если у него самого руки недостаточно прямые. (Так поступает STLport).
Здравствуйте, <Аноним>, Вы писали:
А>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>Типа "настоящие" программисты ошибок не совершают...
"Настоящие" (попрошу заметить кавычки ) предпочитают как можно большее число проверок вынести в compile-time (см. Александреску, Compile-Time Assertions):
Здравствуйте, HiSH, Вы писали:
HSH> Более информативные сообщения об ошибках. Даже если добавить возможность задания имени массива, компилятор не обязан сообщить его в тексте еррора. А имя кривого шаблона — должен. Если верить Александреску
Мне вполне хватает комментария у assert-а. Не вижу причин усложнять конструкцию ради текста в листинге. Всё равно придётся лазить по исходникам для исправления. Кроме того не в любом месте такой ассерт применим.
Здравствуйте, Аноним, Вы писали:
А>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>Типа "настоящие" программисты ошибок не совершают...
Чтобы ассерты имели хоть какой-то смысл необходим полный code coverage при тестировании со всеми возможными входными данными, т.е. чтобы при тестировании отработали все ветки кода на реальных данных. Часто это обеспечить очень сложно, поэтому может легко случиться так, что реальные входные данные вызвали последовательность действий, которые бы были вызвали ассерт, но это уже релизная версия и ассерта там, естественно, нет. Поэтому гораздо безопаснее не полагаться целиком на тестирование и ассерты, а всегда проверять условия в критичных местах.
Здравствуйте, Аноним, Вы писали:
А>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>Типа "настоящие" программисты ошибок не совершают...
очень часто используют. Посмотрите Windows checked билды, там assert-ы на каждом вызове.
Не имеет большого смысла assert-ить свой код, типа
Здравствуйте, pavel_turbin, Вы писали:
_>очень часто используют. Посмотрите Windows checked билды, там assert-ы на каждом вызове. _>Не имеет большого смысла assert-ить свой код, типа
_>
_>имеет смысл assert-ить меж-модульные вызовы и вызовы к операционной системе, пример
_>
_>my_assert( CloseHandle(hFile) ); // обрашение к OS
_>export my_error myfuncchar *a) // вызывается из вне
_>{
_> my_assert(a);
_> if( 0 == a )
_> return invalid_parameter;
_> return ok;
_>}
_>
_>я написал "my_assert", чтобы в debug build он раскрылся в обычный assert, а в relase dump ошибки в лог, если он поддержан.
Это почему еще не имеет смысла ассертить свой код?
Думаю Вам следует прочитать серию статей Александреску про assert'ы и enforcement'ы в C/C++ Users Journal.
Philosophers say that reality defies imagination by being more complex than what our mind can concoct. This is certainly true in the case of software development. There are tons of stories about assertions that were just "impossible to fire," but they actually fired. Time and again, it goes the same way. "This value is certainly positive! That pointer is obviously not null! The array? It's undoubtedly sorted; I'd bet money on that! Why recheck tautologies?" If you're a beginner, you feel like you are wasting your time when you write some assert, but much more often than you initially thought, it's going to fire to save your life. It's all because software development is complex, and anything could happen in a program that is changing. Assertions verify that what you believe is "obviously true" actually stays true.
There is an effective litmus test to differentiate the cases in which you need to use assert and when you need to use genuine error checking: you use error checking for things that could happen, even very improbably. You use assert only for things that you truly believe cannot possibly happen under any circumstances. An assertion that fails always signals a design or a programmer error — not a user error.
On the other hand, you do not want to use assertions to validate return values of functions that might fail. You don't use assert to make sure that malloc worked, that a window creation succeeded, or that a thread was started. You can, use, however, assert to make sure that APIs work as documented. For example, if some API function is documented to always return a positive value, but somehow you suspect it might have a bug, you might want to plant an assert.
Нельзя путать обработку ошибок с отловом багов в коде. Это две большие разницы!
Я присоединяюсь к вопросу. В моем архиве чужих исходников, я не нашел ни одного проекта (библиотеки), где бы последовательно использовались ассерты. Большей частью урывками, в основном для проверки на равенство нулю указателя или использование assert(0) в default блоках оператора switch.
имеет если кодом вызываешь не только ты
потому что с каким параметром будет вызвана функция вообще никто не знает
_>имеет смысл assert-ить меж-модульные вызовы и вызовы к операционной системе, пример
_>
_>my_assert( CloseHandle(hFile) ); // обрашение к OS
_>export my_error myfuncchar *a) // вызывается из вне
_>{
_> my_assert(a);
_> if( 0 == a )
_> return invalid_parameter;
_> return ok;
_>}
_>
_>я написал "my_assert", чтобы в debug build он раскрылся в обычный assert, а в relase dump ошибки в лог, если он поддержан.
а вот это вообще перл
my_assert( CloseHandle(hFile) ); // обрашение к OS
в релизе получаем утечку хендлов
Re[2]: А зачем выбрасывать asserts в release-версии?
Здравствуйте, MaximE, Вы писали:
ME>Часто это обеспечить очень сложно, поэтому может легко случиться так, что реальные входные данные вызвали последовательность действий, которые бы были вызвали ассерт, но это уже релизная версия и ассерта там, естественно, нет. Поэтому гораздо безопаснее не полагаться целиком на тестирование и ассерты, а всегда проверять условия в критичных местах.
А почему бы не оставлять assert'ы и в release-версии?
В конце концов assert выполняет несколько функций
1) Это хороший комментарий мыслей программиста о состоянии программы в данной точке кода. Особенно хорошо, что он формальный и сам проверяет свою актуальность
2) Он позволяет довольно задёшево поймать очень много ошибок.
3) Он повышает доверие к результату работы программы. Типа если программа отработала и все assert'ы успешно проверили свои условия, то результат более надёжен.
4) Это хороший инструмент для поддержки. Обычно, если в программе много assert'ов, то в случае обнаружение ошибки конкретный assert позволяет детектировать конкретную проблему. То есть после того, как один пользователь нашёл такие грабли и ты с ними разобрался, то ты можешь следующему пользователю, у которого такой же assert проваливается, выдать уже готовые рекоммендации. ТОже довольно удобно.
Так что не совсем понятно от чего бы не оставлять assert'ы всегда. Другое дело что может в них лучше делать не авост, а таки бросаться спецальным assert'овским исключением.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
ME>Чтобы ассерты имели хоть какой-то смысл необходим полный code coverage при тестировании со всеми возможными входными данными, т.е. чтобы при тестировании отработали все ветки кода на реальных данных.
Кхм... То есть, если ассерты помогут выловить не все ошибки, а только 90% — то это совершенно бесполезная фича...
Re: Почему редко используются assert'ы?
От:
Аноним
Дата:
07.10.05 18:46
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>Типа "настоящие" программисты ошибок не совершают...
И везде по ходу определения методов SomeClass вместо непосредственно prop2_ использую вызов get_ptop2(), тем самым гарантирую, что я нигде не налажал и значение prop2_ инициализировано верно.
Re[2]: Почему редко используются assert'ы?
От:
Аноним
Дата:
07.10.05 19:27
Оценка:
Здравствуйте, Нахлобуч, Вы писали:
Н>Здравствуйте, <Аноним>, Вы писали:
А>>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>>Типа "настоящие" программисты ошибок не совершают...
Н>"Настоящие" (попрошу заметить кавычки ) предпочитают как можно большее число проверок вынести в compile-time (см. Александреску, Compile-Time Assertions):
Н>
Н>template <class To, class From>
Н>To safe_reinterpret_cast(From from)
Н>{
Н> {
Н> class ERROR_Destination_Type_Too_Narrow {};
Н> (void)sizeof(
Н> CompileTimeChecker<(sizeof(From) <= sizeof(To))>(
Н> ERROR_Destination_Type_Too_Narrow()));
Н> }
Н> return reinterpret_cast<To>(from);
Н>}
Н>
Такой подход я видел еще реже, пожалуй только boost на ум приходит.
Поиск выдал 112 файлов использующих BOOST_STATIC_ASSERT, это из 2940 файлов версии 1.32
Re[2]: Почему редко используются assert'ы?
От:
Аноним
Дата:
07.10.05 19:32
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>>Типа "настоящие" программисты ошибок не совершают...
А>Я например часто использую: А>
А>И везде по ходу определения методов SomeClass вместо непосредственно prop2_ использую вызов get_ptop2(), тем самым гарантирую, что я нигде не налажал и значение prop2_ инициализировано верно.
Может кто-то считает более грамотным, проверять все входные величины сразу прямо в конструкторе, а не в момент их первого использования? Будет очень интересно послушать мнения на этот счет.
Здравствуйте, Аноним, Вы писали: А>Здравствуйте, Аноним, Вы писали: А>>Здравствуйте, Аноним, Вы писали:
брр. Сколько разных анонимов!
А>>>Почему в большинстве библиотек которые я видел очень редко используются assert'ы?
да потому, что библиотеки отличаются от проектов. Грубо говоря, библиотеки должны иметь специфицированное поведение.
а кому нравится писать, вот при включеном макросе будет выдаваться assert при неправильных параметрах.
библиотека должна что-то делать и при вкл assert и при выклЮ и лучше одно и тоже.
А>>>Типа "настоящие" программисты ошибок не совершают...
а это вообюще странно, а проверяется результат ф-ии. я бы проверял при записи неврного значения.
А>>И везде по ходу определения методов SomeClass вместо непосредственно prop2_ использую вызов get_ptop2(), тем самым гарантирую, что я нигде не налажал и значение prop2_ инициализировано верно.
тогда это должны быть А>Может кто-то считает более грамотным, проверять все входные величины сразу прямо в конструкторе, а не в момент их первого использования? Будет очень интересно послушать мнения на этот счет.
по мне, так проверять надо там, где они могут быть ошибочными, при этом
1. коструктор это или нет не волнует
2. но если const, то в конструкторе проверка, естествено эффективней
3. надо различать проверку значений, которые вводит пользователь, и это должно входит в алгоритм обработки входных данных, а не в assert, и перестраховку программисткую.
---
С уважением,
Сергей Мухин
Re[2]: compile time assert'ы
От:
Аноним
Дата:
08.10.05 08:09
Оценка:
Здравствуйте, Нахлобуч, Вы писали:
Н>Здравствуйте, <Аноним>, Вы писали:
Н>"Настоящие" (попрошу заметить кавычки ) предпочитают как можно большее число проверок вынести в compile-time (см. Александреску, Compile-Time Assertions):
Почему в кавычках?
Н>Использование:
В смыслле использования я предпочитаю
//ASSERT времени компиляции. Может быть помещён почти в любом месте программы.#define TASSERT(COND1T1ON) typedef int TASSERT_fict1ve_namE[(COND1T1ON)?1:-1];
Здравствуйте, Аноним, Вы писали:
А>В смыслле использования я предпочитаю
А>
А>//ASSERT времени компиляции. Может быть помещён почти в любом месте программы.
А>#define TASSERT(COND1T1ON) typedef int TASSERT_fict1ve_namE[(COND1T1ON)?1:-1];
А>
А>И не вижу преимуществ у Александреску.
Более информативные сообщения об ошибках. Даже если добавить возможность задания имени массива, компилятор не обязан сообщить его в тексте еррора. А имя кривого шаблона — должен. Если верить Александреску
Здравствуйте, HiSH, Вы писали:
HSH>Здравствуйте, Аноним, Вы писали:
HSH> Более информативные сообщения об ошибках. Даже если добавить возможность задания имени массива, компилятор не обязан сообщить его в тексте еррора. А имя кривого шаблона — должен. Если верить Александреску
Ничего компилятор не обязан. Он просто обязан сообщить, что код ill-formed.
Неа. Вот например gcc не сообщает. А про имя массива сообщает. В MSVC ровно наоборот.
И вообще, лишний код просто ради формирования сообщения об ошибке, что не работает на разных компиляторах — нафиг это надо? Чем проще, тем лучше.
Надежней написать рядом комментарий. И он может быть более удобочитаемым — можно даже http://ссылку туда всунуть.
Правильно работающая программа — просто частный случай Undefined Behavior
Re[2]: Почему редко используются assert'ы?
От:
Аноним
Дата:
08.10.05 20:25
Оценка:
Здравствуйте, MaximE, Вы писали:
ME>Здравствуйте, Аноним, Вы писали:
А>>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>>Типа "настоящие" программисты ошибок не совершают...
ME>Чтобы ассерты имели хоть какой-то смысл необходим полный code coverage при тестировании со всеми возможными входными данными, т.е. чтобы при тестировании отработали все ветки кода на реальных данных. Часто это обеспечить очень сложно, поэтому может легко случиться так, что реальные входные данные вызвали последовательность действий, которые бы были вызвали ассерт, но это уже релизная версия и ассерта там, естественно, нет. Поэтому гораздо безопаснее не полагаться целиком на тестирование и ассерты, а всегда проверять условия в критичных местах.
ASSERT — это фича только для разработчиков кода, а не для юзера. Ассертами я проверяю самого себя во время работы над проектом, а юзера я проверяю непосредственно при вводе им значений, например если в edit'е введено неверное значение, всплывает диалог, типа "Попробуйте еще раз...".
Все реальные входные данные, естественно проверяются и в debug, и в release, потому что это данные поступающие от пользователя, т.к. входные.
Может я путано объяснил... но, если кратко, ассерты — это инструмент для разработчика. Для данных поступающих в программу от пользователя используются другие методы проверки: обычные условия, с выводом сообщения при отрицательном результате или выбросом исключения или еще что-то
Здравствуйте, <Аноним>, Вы писали:
А>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>Типа "настоящие" программисты ошибок не совершают...
Да нет , асерты используются на полную при разработке и отладке , а уже из отлаженных кусков кода обычно удалаяютяс.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: Почему редко используются assert'ы?
От:
Аноним
Дата:
08.10.05 21:14
Оценка:
Здравствуйте, minorlogic, Вы писали:
M>Здравствуйте, <Аноним>, Вы писали:
А>>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>>Типа "настоящие" программисты ошибок не совершают...
M>Да нет , асерты используются на полную при разработке и отладке , а уже из отлаженных кусков кода обычно удалаяютяс.
Что за бред удалять асерты??? Они же в релизе и так не срабатывают.
Ну, и про инварианты тут выше поветке правильно сказали.
Re[3]: Почему редко используются assert'ы?
От:
Аноним
Дата:
08.10.05 21:41
Оценка:
Здравствуйте, Cyberax, Вы писали: C>Кстати, у ассертов под MSVC есть еще одно интересное применение: C>
C>То есть assert'ы не просто удаляются из кода, а превращаются в хинты C>компилятору.
Вообще-то поведение CRT макроса assert определяется макросом NDEBUG.
Макросом DEBUG определяется поведение _ASSERT и _ASSERTE.
Re[5]: Почему редко используются assert'ы?
От:
Аноним
Дата:
09.10.05 06:30
Оценка:
Здравствуйте, sch, Вы писали:
sch>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Cyberax, Вы писали: C>>>Кстати, у ассертов под MSVC есть еще одно интересное применение: C>>>
C>>>То есть assert'ы не просто удаляются из кода, а превращаются в хинты C>>>компилятору.
А>>А можно про это поподробнее, почему это лучше чем ((void)0) в релизе вместо ассерта?
sch>http://msdn.microsoft.com/library/en-us/vccelng/htm/msmod_36.asp:
sch>The __assume keyword passes a hint to the optimizer. The optimizer assumes that the condition represented by expression is true at the point where the keyword appears and remains true until expression is altered (for example, by assignment to a variable). Selective use of hints passed to the optimizer by __assume can improve optimization.
MSDN я читал, но все равно не понял чем лучше ((void)0), поэтому и спрашиваю.
Здравствуйте, minorlogic, Вы писали:
M>Здравствуйте, <Аноним>, Вы писали:
А>>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>>Типа "настоящие" программисты ошибок не совершают...
M>Да нет , асерты используются на полную при разработке и отладке , а уже из отлаженных кусков кода обычно удалаяютяс.
asserts удаляются автоматически компилятором и препроцессором во время построения release версии.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>>Типа "настоящие" программисты ошибок не совершают...
А>Я например часто использую: А>
А>И везде по ходу определения методов SomeClass вместо непосредственно prop2_ использую вызов get_ptop2(), тем самым гарантирую, что я нигде не налажал и значение prop2_ инициализировано верно.
Вообще этот тот случай, когда лучше использовать исключения. Если рассматривать SomeClass как модель данных, то опытный программист помимо структуры данных включает еще код для constraine, то есть определяет код который следит за правильными корректными состояниями модели данных, в случае если пользователь этой структуры вводит модель данных в неправильное состояние — пользовательский код должен получить ошибку, в обьектноориентированных языках для этих целей принято использовать исключения, и пользовательский код обязан переживать такие ситуации, к примеру код, который визуализирует в ГУИ эту структуру должен знать, что при установке значений поля структуры могут быть исключительные ситуации, и нужно уметь правильно это обработать, проверка целостности структуры должна быть заключена в самой структуре, а не на уровне ГУИ.
Бывает правда другая ситуация, вы используете низлежащую функциональность, low level API, и его поведение не достаточно хорошо изучено, есть некоторые непредсказуемые поведения, нет доверия производителю этой функциональности, вот тут после каждого обращения к этому функционалу следует его проверять ассертами, это помимо исключений, которые по прежнему должны улететь в пользовательский код, с тем что бы попробовать еще раз дать шанс заполнить данные, может глюк нижнего ненадежного слоя и не повторится.
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Re[3]: Почему редко используются assert'ы?
От:
Аноним
Дата:
09.10.05 11:08
Оценка:
Здравствуйте, Batiskaf, Вы писали:
B>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Аноним, Вы писали:
А>>>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>>>Типа "настоящие" программисты ошибок не совершают...
А>>Я например часто использую: А>>
А>>И везде по ходу определения методов SomeClass вместо непосредственно prop2_ использую вызов get_ptop2(), тем самым гарантирую, что я нигде не налажал и значение prop2_ инициализировано верно.
B>Вообще этот тот случай, когда лучше использовать исключения. Если рассматривать SomeClass как модель данных, то опытный программист помимо структуры данных включает еще код для constraine, то есть определяет код который следит за правильными корректными состояниями модели данных, в случае если пользователь этой структуры вводит модель данных в неправильное состояние — пользовательский код должен получить ошибку, в обьектноориентированных языках для этих целей принято использовать исключения, и пользовательский код обязан переживать такие ситуации, к примеру код, который визуализирует в ГУИ эту структуру должен знать, что при установке значений поля структуры могут быть исключительные ситуации, и нужно уметь правильно это обработать, проверка целостности структуры должна быть заключена в самой структуре, а не на уровне ГУИ.
B>Бывает правда другая ситуация, вы используете низлежащую функциональность, low level API, и его поведение не достаточно хорошо изучено, есть некоторые непредсказуемые поведения, нет доверия производителю этой функциональности, вот тут после каждого обращения к этому функционалу следует его проверять ассертами, это помимо исключений, которые по прежнему должны улететь в пользовательский код, с тем что бы попробовать еще раз дать шанс заполнить данные, может глюк нижнего ненадежного слоя и не повторится.
Ниже по ветке я уже говорил, что assert'ы нужны для разработчика кода, не для пользователя exe'шника.
Все данные вводимые пользователем проверяются сразу при их вводе (вот где используютеся код constraine класса SomeClass, напр. is_valid_prop2()), в случае неудачной проверки, выводится сообщение, где предлагается ввести корректные данные, или выбрасывается исключение, зависит от типа приложения. Коду SomeClass неважно где его будут использовать, поэтому он не знает что делать в случае неверного prop2_: исключение, код ошибки, сообщение... Задача разработчика класса SomeClass предоставить набор методов валидации данных; задача разработчика приложения, использующего SomeClass, пропускать все входные данные для SomeClass, вводимые пользователем, через соответствующие функции валидации, и написать код для обработки некорректных входных данных.
Т. о. при таком подходе свойства класса prop2_ и prop1_ не могут быть инициированы неверными значениями.
Здравствуйте, ssi, Вы писали:
ssi>Это почему еще не имеет смысла ассертить свой код? ssi>Думаю Вам следует прочитать серию статей Александреску про assert'ы и enforcement'ы в C/C++ Users Journal.
это все так красиво выглядит теории. На практике, когда необходимо достичь определеного качества кода за заданных промежуток времени, чем-то приходиться пренебрегать. Конечно, если время неограниченно, то очень хорошо "проассертить" весь код, но я думаю, что лучше прогнать ещё пару unit-test или дописать коменты, чем возиться с assert-ом. Так или иначе assert-ы уйдут из releasa сами.
Здравствуйте, pavel_turbin, Вы писали:
_>это все так красиво выглядит теории. На практике, когда необходимо достичь определеного качества кода за заданных промежуток времени, чем-то приходиться пренебрегать. Конечно, если время неограниченно, то очень хорошо "проассертить" весь код, но я думаю, что лучше прогнать ещё пару unit-test или дописать коменты, чем возиться с assert-ом. Так или иначе assert-ы уйдут из releasa сами.
А что с ними возится, тупо ставишь ассерты на все входные данные хотя бы, уже кучу багов можно отловить. По времени это сопоставимо с написанием коментария. Собственно, ассерты — это коментарий для релиза.
Здравствуйте, Аноним, Вы писали:
А>Ниже по ветке я уже говорил, что assert'ы нужны для разработчика кода, не для пользователя exe'шника.
Да собственно и исключения тоже для программиста. Просто если провести грань между средствами верификации, то исключения я применяю там где нужно оповестить пользовательский код о неправильной операции, а ассерты я применяю на уровне моего системного кода для проверки неотлаженного низлежащего кода.
А>Все данные вводимые пользователем проверяются сразу при их вводе (вот где используютеся код constraine класса SomeClass, напр. is_valid_prop2()), в случае неудачной проверки, выводится сообщение, где предлагается ввести корректные данные, или выбрасывается исключение, зависит от типа приложения. Коду SomeClass неважно где его будут использовать, поэтому он не знает что делать в случае неверного prop2_: исключение, код ошибки, сообщение... Задача разработчика класса SomeClass предоставить набор методов валидации данных; задача разработчика приложения, использующего SomeClass, пропускать все входные данные для SomeClass, вводимые пользователем, через соответствующие функции валидации, и написать код для обработки некорректных входных данных.
да, только сообщениями пользоваться не стоит, SomeClass может использоваться в самых разных средах, с разными типами аллертов. Принимать решение о выбрасывании сообщений должен пользовательский код, если он может показать месаджбокс или распечатать html, или бибикнуть на экране деньгомата в банке, в зависимости от системы.
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Re[5]: Почему редко используются assert'ы?
От:
Аноним
Дата:
09.10.05 13:11
Оценка:
Здравствуйте, Batiskaf, Вы писали:
А>>Все данные вводимые пользователем проверяются сразу при их вводе (вот где используютеся код constraine класса SomeClass, напр. is_valid_prop2()), в случае неудачной проверки, выводится сообщение, где предлагается ввести корректные данные, или выбрасывается исключение, зависит от типа приложения. Коду SomeClass неважно где его будут использовать, поэтому он не знает что делать в случае неверного prop2_: исключение, код ошибки, сообщение... Задача разработчика класса SomeClass предоставить набор методов валидации данных; задача разработчика приложения, использующего SomeClass, пропускать все входные данные для SomeClass, вводимые пользователем, через соответствующие функции валидации, и написать код для обработки некорректных входных данных.
B>да, только сообщениями пользоваться не стоит, SomeClass может использоваться в самых разных средах, с разными типами аллертов. Принимать решение о выбрасывании сообщений должен пользовательский код, если он может показать месаджбокс или распечатать html, или бибикнуть на экране деньгомата в банке, в зависимости от системы.
Так вроде и написано
>> Коду SomeClass неважно где его будут использовать, поэтому он не знает что делать в случае неверного prop2_: исключение, код ошибки, сообщение...
Здравствуйте, Аноним, Вы писали:
А>Ниже по ветке я уже говорил, что assert'ы нужны для разработчика кода, не для пользователя exe'шника.
вот и нет. Посмотрите на Windows XP Checked build. Он полон assert-ов. Их цель выловить ошибки в вызовах и использования API. Вместо того, чтобы вернуть FALSE, checked build генерирюет assert, который ловится отладчиком. Я всегда перед релизом прогоняю тесты покрайней мере один раз на checked. Периодически нахожу что-нибудь.
_>это все так красиво выглядит теории. На практике, когда необходимо достичь определеного качества кода за заданных промежуток времени, чем-то приходиться пренебрегать. Конечно, если время неограниченно, то очень хорошо "проассертить" весь код, но я думаю, что лучше прогнать ещё пару unit-test или дописать коменты, чем возиться с assert-ом. Так или иначе assert-ы уйдут из releasa сами.
IMHO, ставить или не ставить ассерты — дело привычки, кто-то ставит много, кто-то мало или вообще не ставит. Но они очень полезны при отладке проекта, и особенно полезны, когда проект достаточно большой, и изменение одного из модулей потенциально может затронуть другие части. Поэтому я всегда ставлю досаточно много ассертов на логику, чтобы хоть какое предупреждение получить в ситуации, когда отлаженный модуль перестал корректно работать из-за изменений в других частях проекта. В общем, это не панацея, но помощь в отладке есть.
C>То есть assert'ы не просто удаляются из кода, а превращаются в хинты C>компилятору.
Спасибо, узнал про наличие такого ключевого слова
Но в реальном проекте я бы побоялся ипользовать его везде где я использую ASSERT — хотя бы потому что бывают такие куски кода
if (param == NULL)
{
ATLASSERT(param && "Invalid parameter, but error is not critical");
return E_FAIL;
}
Боюсь, что в случае __assume вместо ASSERT оптимизатор этот кусок вообще выкинет.
I>my_assert( CloseHandle(hFile) ); // обрашение к OS
I>
Кстати, из-за высокой вероятности спутать ASSERT и VERIFY мы у себя в проекте вообще отказались от использования VERIFY — если надо сделать ASSERT на возвращаемое значение — пиши
А>>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>>Типа "настоящие" программисты ошибок не совершают...
К>Потому что assert — это самое убогое средство отладки, какое можно придумать. К>В дебаг-версии он выводит assertion failed и убивает задачу по abort. В релиз-версии не вычисляет аргумент (повод для ошибок, когда важная функциональность случайно внесена внутрь assert-выражения).
Нарушения допущений (assertion failure) могут быть разными
— по степени воздействия (от аварийного завершения до возобновляемого отказа в обслуживании)
— по трактовке (нарушение предусловий со стороны клиентского кода, внутренние ошибки)
— по способности к отладке (нужно ли останавливать отладчик, или можно просто отказать в обслуживании; нужно ли вести журнал и т.д.)
— по механизмам реализации (вызов аварийной функции, бросок исключения, возвращение кода ошибки и т.д.; как выводить сообщения в журнал и на экран; интеграция с отладчиком)
По-хорошему, получается, что нужно написать библиотеку поддержки assert'ов на разные случаи жизни.
Перекуём баги на фичи!
Re[3]: Почему редко используются assert'ы?
От:
Аноним
Дата:
10.10.05 17:54
Оценка:
Здравствуйте, Кодт, Вы писали:
А>>>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>>>Типа "настоящие" программисты ошибок не совершают...
К>>Потому что assert — это самое убогое средство отладки, какое можно придумать. К>>В дебаг-версии он выводит assertion failed и убивает задачу по abort. В релиз-версии не вычисляет аргумент (повод для ошибок, когда важная функциональность случайно внесена внутрь assert-выражения).
К>Нарушения допущений (assertion failure) могут быть разными К>- по степени воздействия (от аварийного завершения до возобновляемого отказа в обслуживании) К>- по трактовке (нарушение предусловий со стороны клиентского кода, внутренние ошибки) К>- по способности к отладке (нужно ли останавливать отладчик, или можно просто отказать в обслуживании; нужно ли вести журнал и т.д.) К>- по механизмам реализации (вызов аварийной функции, бросок исключения, возвращение кода ошибки и т.д.; как выводить сообщения в журнал и на экран; интеграция с отладчиком)
К>По-хорошему, получается, что нужно написать библиотеку поддержки assert'ов на разные случаи жизни.
Что используете Вы, вместо ассертов?
Как ловите баги СВОЕГО кода?
Здравствуйте, Аноним, Вы писали:
К>>По-хорошему, получается, что нужно написать библиотеку поддержки assert'ов на разные случаи жизни.
А>Что используете Вы, вместо ассертов? А>Как ловите баги СВОЕГО кода?
Написана библиотека умных ассертов — отчасти, по мотивам советов Герба Саттера. (См. какую-то из его Exceptional книжек).
Есть ряд макросов, словесно описывающих суть ассерта — PRECONDITION, POSTCONDITION, ASSERTION общего назначения.
Они проверяют условия и в случае облома
— проходят через контрольную точку (где можно остановиться для отладки)
— кидают специальное исключение, которое
— — при размотке стека пишет в журнал, в каких функциях произошёл отстрел
— — ловится в самой нижней функции потока, откуда принимается решение остановить работу, перезапустить и т.д.
Есть здоровенное семейство макросов, которые прозрачно проверяют возвращаемые из функций коды ошибок (HRESULT'ы).
Оттуда можно или кинуться исключением подкласса logic_error (типа, штатная неприятность), или объявить assertion fault как выше.
Опять же, это средство самодокументирования кода.
Сейчас библиотека, во-первых, ещё довольно сырая (много велосипедных решений), а во-вторых, не public domain. Так что, увы, поделиться кодом не могу
Здравствуйте, Аноним, Вы писали:
А>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>Типа "настоящие" программисты ошибок не совершают...
С. Макконнелл ("Совершенный код") говорит насчет ассертов так: "Используйте процедуры обработки ошибок для ожидаемых событий и
утверждения для событий, которые происходить не должны"
То есть, если входные данные поступили в функцию из ненадежного источника (пользователя), надо использовать процедуру обработки ошибок, иначе можно обойтись утверждением.
Например, для проверки предусловий в открытых членах класса следует использовать обработку ошибок (исключения или коды возврата), для внутренних (приватных, защищенных) – утверждения (assert)
-- Андрей
Re[5]: compile time assert'ы
От:
Аноним
Дата:
11.10.05 09:23
Оценка:
Здравствуйте, _Winnie, Вы писали:
_W>И вообще, лишний код просто ради формирования сообщения об ошибке, что не работает на разных компиляторах — нафиг это надо? Чем проще, тем лучше.
Ха-ха-ха. Кто бы говорил.
Re[5]: Почему редко используются assert'ы?
От:
Аноним
Дата:
11.10.05 16:38
Оценка:
Здравствуйте, Кодт, Вы писали:
Судя по вашим топикам на rsdn, Вы уже давно занимаетесь разработкой программ. Почему
>> Сейчас библиотека, во-первых, ещё довольно сырая (много велосипедных решений)
Ваш опыт разработок так и не привел к завершенной библиотеке?
Странная вещь получается, есть много разработчиков годы пишущих на Си, так и не решивших для себя каким образом использовать ассерты. Многие опытные разработчики вообще их не используют: сужу по куче библиотек в инете без единой строчки assert(...). Почему?
<...>
АК>То есть, если входные данные поступили в функцию из ненадежного источника (пользователя), надо использовать процедуру обработки ошибок, иначе можно обойтись утверждением.
АК>Например, для проверки предусловий в открытых членах класса следует использовать обработку ошибок (исключения или коды возврата)
Нарушения предусловия — баг программы (на то оно и предусловие, а не "ожидаемое событие"). Что толку от обработки ошибок в этом случае?
Корректность входных данных не может являться предусловием для функции, обрабатывающей данные из ненаднжного источника.
АК>для внутренних (приватных, защищенных) – утверждения (assert)
Только вот эти внутренние методы вызываются обычно из открытого интерфейса. Такое разделение IMHO нелогично.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Кодт, Вы писали:
А>Судя по вашим топикам на rsdn, Вы уже давно занимаетесь разработкой программ. Почему
>>> Сейчас библиотека, во-первых, ещё довольно сырая (много велосипедных решений)
А>Ваш опыт разработок так и не привел к завершенной библиотеке?
А>Странная вещь получается, есть много разработчиков годы пишущих на Си, так и не решивших для себя каким образом использовать ассерты. Многие опытные разработчики вообще их не используют: сужу по куче библиотек в инете без единой строчки assert(...). Почему?
А>Наверное, это риторический вопрос...
дык одно дело библиотека, другое приложение. Вот пример библиотечной ф-ии
double sqrt( double X ) {
assert( X >= 0.0 );
// тра-тата
}
или
double sqrt( double X ) {
if( X < 0.0 ) throw ....
// тра-тата
}
что лучше для библиотеки?
---
С уважением,
Сергей Мухин
Re[7]: Почему редко используются assert'ы?
От:
Аноним
Дата:
11.10.05 18:06
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:
СМ>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Кодт, Вы писали:
А>>Судя по вашим топикам на rsdn, Вы уже давно занимаетесь разработкой программ. Почему
>>>> Сейчас библиотека, во-первых, ещё довольно сырая (много велосипедных решений)
А>>Ваш опыт разработок так и не привел к завершенной библиотеке?
А>>Странная вещь получается, есть много разработчиков годы пишущих на Си, так и не решивших для себя каким образом использовать ассерты. Многие опытные разработчики вообще их не используют: сужу по куче библиотек в инете без единой строчки assert(...). Почему?
А>>Наверное, это риторический вопрос...
СМ>дык одно дело библиотека, другое приложение. Вот пример библиотечной ф-ии
СМ>
СМ>double sqrt( double X ) {
СМ>assert( X >= 0.0 );
СМ>// тра-тата
СМ>}
СМ>
СМ>или
СМ>
СМ>double sqrt( double X ) {
СМ>if( X < 0.0 ) throw ....
СМ>// тра-тата
СМ>}
СМ>
СМ>что лучше для библиотеки?
Т.е. по вашему как раз библиотекам ассерты и не нужны? А нужны они только приложениям
Считаю что для проверки входных данных функции лучше использовать assert.
Проверять валидность данных нужно до вызова функции с этими данными.
double sqrt( double X )
{
assert( X >= 0.0 );
тра-тата
}
if (X < 0) throw...;
if (Y == 0) throw...;
...
sqrt(X);
log(Y);
Assert нужен разработчику кода, использующему данную библиотеку, на тот случай если он где-то забыл проверить данные поступившие от пользователя.
Здравствуйте, Аноним, Вы писали:
А>Т.е. по вашему как раз библиотекам ассерты и не нужны? А нужны они только приложениям А>Считаю что для проверки входных данных функции лучше использовать assert. А>Проверять валидность данных нужно до вызова функции с этими данными.
А>Assert нужен разработчику кода, использующему данную библиотеку, на тот случай если он где-то забыл проверить данные поступившие от пользователя.
данные поступившие от пользоватля, надо проверять логикой (т.е. if), а ассерты то есть, то нет (в release).
аналогично в библиотеке, вам дают ф-ию, и говорят, "вот ее поведение, оно отлично от при разных режимах компиляции" и такое терпеть?
Здравствуйте, Аноним, Вы писали:
>>> Сейчас библиотека, во-первых, ещё довольно сырая (много велосипедных решений)
А>Ваш опыт разработок так и не привел к завершенной библиотеке?
Опыт разработок и опыт сопровождения проектов — это разные вещи
Здравствуйте, Alxndr, Вы писали:
A>Здравствуйте, Андрей Коростелев, Вы писали:
A><...>
АК>>То есть, если входные данные поступили в функцию из ненадежного источника (пользователя), надо использовать процедуру обработки ошибок, иначе можно обойтись утверждением. АК>>Например, для проверки предусловий в открытых членах класса следует использовать обработку ошибок (исключения или коды возврата) A>Нарушения предусловия — баг программы (на то оно и предусловие, а не "ожидаемое событие"). Что толку от обработки ошибок в этом случае? A>Корректность входных данных не может являться предусловием для функции, обрабатывающей данные из ненаднжного источника. АК>>для внутренних (приватных, защищенных) – утверждения (assert) A>Только вот эти внутренние методы вызываются обычно из открытого интерфейса. Такое разделение IMHO нелогично.
Ну смотри
Классическое представление ошибки — это цепочка Fault->Error->Failure (поцарапали DVD->сбойные блоки->файловый сервис обломается при попытке чтения этих блоков)
В то же время одно и то же Error-событие может рассматириваться как Fault в зависимости от контекста (например, если облом файлового сервиса для нас не фатален, так как мы можем это обработать в нашей програме)
В нашем случае имеем два контекста: пользовательский и системный (или назовем его программистский)
При возникновении ошибки в пользовательском контексте, система должна обработать ее на пользовательском уровне (выкинуть message box что пользователь был вообще-то неправ, введя "Леха" на запрос даты рождения)
Программистские же ошибки обрабатываются на программистском уровне (вылет + корка чтоб было над чем подумать).
С точки зрения пользовательского контекста имеем Fault: пользователь неверно ввел строку.
Error: функция открытого интерфейса получила неверные данные.
Теперь смотрим с точки зрения программиста: Fault: функция открытого интерфейса передала внутренней неверные входные данные
Error: assertion внутренней функции.
Отсюда видно, что assertion служит для контроля ошибок программиста, иначе ошибки следует обрабатывать
Здравствуйте, Андрей Коростелев, Вы писали:
АК>Классическое представление ошибки — это цепочка Fault->Error->Failure (поцарапали DVD->сбойные блоки->файловый сервис обломается при попытке чтения этих блоков) АК>В то же время одно и то же Error-событие может рассматириваться как Fault в зависимости от контекста (например, если облом файлового сервиса для нас не фатален, так как мы можем это обработать в нашей програме)
АК>В нашем случае имеем два контекста: пользовательский и системный (или назовем его программистский) АК>При возникновении ошибки в пользовательском контексте, система должна обработать ее на пользовательском уровне (выкинуть message box что пользователь был вообще-то неправ, введя "Леха" на запрос даты рождения) АК>Программистские же ошибки обрабатываются на программистском уровне (вылет + корка чтоб было над чем подумать).
АК>С точки зрения пользовательского контекста имеем Fault: пользователь неверно ввел строку. АК>Error: функция открытого интерфейса получила неверные данные. АК>Теперь смотрим с точки зрения программиста: Fault: функция открытого интерфейса передала внутренней неверные входные данные АК>Error: assertion внутренней функции.
АК>Отсюда видно, что assertion служит для контроля ошибок программиста, иначе ошибки следует обрабатывать
Ещё один момент: насколько вообще нужна отказоустойчивость?
Если ошибка программиста привела к сбою в недрах библиотеки — то, в конце концов, какая разница: дать ему по пальцам там или попытаться восстановиться (вернув код ошибки или исключение — которые в клиентском коде могут быть подавлены!) Фатальность предпочтительнее потому, что его легче обслужить, во-первых, и сложнее проигнорировать, во-вторых.
Если же ошибка в клиентском коде навела сбой в серверном приложении, то гораздо предпочтительнее восстановиться — пусть даже ценой замалчивания.
Здравствуйте, Аноним, Вы писали:
А>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>Типа "настоящие" программисты ошибок не совершают...
Ну стандартный assert из runtime действительно весьма убог. Тут я с Кодт'ом вполне согласен.
Но сейчас есть много библиотек в которых разработаны более продвинутые версии макроса assert.
И, насколько я знаю, ими вполне пользуются.
Правда в развитых версиях assert'а есть много отличий, от стандартного.
1) Обычно есть несколько разных assert, которые убираются или не убираются в зависимости от того debug версия или нет
2) Обычно есь возможность управлять что будет, в случае провала условния в assert. При этом отдельно можно управлять что будет, если провалится условие, при инициализации статического объекта, а отдельно, если из кода, вызванного из main
3) Дефолтное поведение разное для разных контекстов. Например под Windows, для окошечного приложения -- MessageBox и исключение, для консольного -- вывод в консоль и исключение, а для сервиса запись в лог и исключение. Ну а в случае провала условия в конструкторе статического объекта -- исключение не кидается, потому что негде ловить.
Ну такое что-нибудь например. Возможны и более проработанные варианты. Например, обработчик может сразу формировать запрос в техподдержку и открывать в браузере страничку на сайте производителя софта, где возмможно уже описано что делать, в случае появления именно такого assert
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Почему редко используются assert'ы?
От:
Аноним
Дата:
13.10.05 18:27
Оценка:
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Аноним, Вы писали:
А>>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>>Типа "настоящие" программисты ошибок не совершают...
E>Ну стандартный assert из runtime действительно весьма убог. Тут я с Кодт'ом вполне согласен. E>Но сейчас есть много библиотек в которых разработаны более продвинутые версии макроса assert. E>И, насколько я знаю, ими вполне пользуются.
E>Правда в развитых версиях assert'а есть много отличий, от стандартного.
E>1) Обычно есть несколько разных assert, которые убираются или не убираются в зависимости от того debug версия или нет E>2) Обычно есь возможность управлять что будет, в случае провала условния в assert. При этом отдельно можно управлять что будет, если провалится условие, при инициализации статического объекта, а отдельно, если из кода, вызванного из main E>3) Дефолтное поведение разное для разных контекстов. Например под Windows, для окошечного приложения -- MessageBox и исключение, для консольного -- вывод в консоль и исключение, а для сервиса запись в лог и исключение. Ну а в случае провала условия в конструкторе статического объекта -- исключение не кидается, потому что негде ловить.
E>Ну такое что-нибудь например. Возможны и более проработанные варианты. Например, обработчик может сразу формировать запрос в техподдержку и открывать в браузере страничку на сайте производителя софта, где возмможно уже описано что делать, в случае появления именно такого assert
Вопрос был не о конкретно стандартном макросе assert, а об ассерте как концепции отлова багов
Здравствуйте, Аноним, Вы писали: А>Вопрос был не о конкретно стандартном макросе assert, а об ассерте как концепции отлова багов
Наверное в публичные библиотеки не хотят тащить за собой нестандартный assert.
Но, тем не менее, например, приватные библиотеки, которые существуют в той конторе, где работаю (довольно большой) пользуются стандортизованной в конторе библиотекой assert'ов, и, соответсвенно ставят assert'ы везде где это надо.
Ну а в приложениях вообще постоянно ставят assert'ы, так что я думаю, дело в том, что стандартный assert убог, а остальные не стандартизованы.
Если, когда, в STL добавят нормальный assert его станут использовать и в библиотеках
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>... так что я думаю, дело в том, что стандартный assert убог, а остальные не стандартизованы. E>Если, когда, в STL добавят нормальный assert его станут использовать и в библиотеках
ИМХО, конечно, это не вопрос стандартности, но культуры программирования, тестирования и сопровождения. Точнее её отсутствия. С другой стороны, сама она не возникнет, культуру надо прививать. Делать же это обычно никому не хочется. То что ассёрты как приём программирования являются причиной спров о нужности, просто показатель.
Здравствуйте, Alexey Chen, Вы писали:
AC>ИМХО, конечно, это не вопрос стандартности, но культуры программирования, тестирования и сопровождения. Точнее её отсутствия. С другой стороны, сама она не возникнет, культуру надо прививать. Делать же это обычно никому не хочется. То что ассёрты как приём программирования являются причиной спров о нужности, просто показатель.
Да нет, вроде как про пользу assert'ов особо-то никто тут не спорил
Не нравилось поведение стандартного assert'а
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, MaximE, Вы писали:
ME>Чтобы ассерты имели хоть какой-то смысл необходим полный code coverage при тестировании со всеми возможными входными данными, т.е. чтобы при тестировании отработали все ветки кода на реальных данных. Часто это обеспечить очень сложно
Можешь привести пример, когда полный code coverage действительно очень сложен?
Здравствуйте, Alxndr, Вы писали:
A>Здравствуйте, MaximE, Вы писали:
ME>>Чтобы ассерты имели хоть какой-то смысл необходим полный code coverage при тестировании со всеми возможными входными данными, т.е. чтобы при тестировании отработали все ветки кода на реальных данных. Часто это обеспечить очень сложно
A>Можешь привести пример, когда полный code coverage действительно очень сложен?
Здравствуйте, MaximE, Вы писали:
ME>>>Чтобы ассерты имели хоть какой-то смысл необходим полный code coverage при тестировании со всеми возможными входными данными, т.е. чтобы при тестировании отработали все ветки кода на реальных данных. Часто это обеспечить очень сложно
A>>Можешь привести пример, когда полный code coverage действительно очень сложен?
ME>Не могу ни вспомнить, ни придумать
Еще вопрос: если мы имеем полный code coverage — нафига нам вообще нужны assert'ы?
Здравствуйте, Аноним, Вы писали:
А>Почему в большинстве библиотек которые я видел очень редко используются assert'ы? А>Типа "настоящие" программисты ошибок не совершают...
CPPUNIT_ASSERT чем плох?
Конечно, я слышал кучу мнений по поводу юнит-тестирования, но большинство из них сводилось к "некогда мне тут фигней заниматься"
Здравствуйте, Alxndr, Вы писали:
A>Здравствуйте, MaximE, Вы писали:
ME>>>>Чтобы ассерты имели хоть какой-то смысл необходим полный code coverage при тестировании со всеми возможными входными данными, т.е. чтобы при тестировании отработали все ветки кода на реальных данных. Часто это обеспечить очень сложно
A>>>Можешь привести пример, когда полный code coverage действительно очень сложен?
ME>>Не могу ни вспомнить, ни придумать
A>Еще вопрос: если мы имеем полный code coverage — нафига нам вообще нужны assert'ы?
Здравствуйте, MaximE, Вы писали:
A>>Еще вопрос: если мы имеем полный code coverage — нафига нам вообще нужны assert'ы?
ME>Мне они не нужны, я их не использую )
Alxndr wrote:
> Здравствуйте, MaximE, Вы писали: > > A>>Еще вопрос: если мы имеем полный code coverage — нафига нам вообще > нужны assert'ы? > > ME>Мне они не нужны, я их не использую ) > > Ну, вопрос был "вообще", теоретический. > > А что используешь? Сразу abort()?
Если после ошибки есть возможность восстановиться, то throw, если нет, то abort().
-- Maxim Yegorushkin
No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Здравствуйте, MaximE, Вы писали:
>> Если после ошибки есть возможность восстановиться, то throw, если нет, то abort().
Так если выше не перехватывать исключение, то обработка его по-умолчанию приведет к abort.
На счет применения assert на этапе кодирования:
1) можно применять assert, чтобы не замарачиваться изобретением способа себя подстраховать в процессее отладки, а заниматься чисто кодированием, тогда — сам написал — сам отгребай свои assert'ы.
2) если я беру чужой недописаный код, где есть куча assert, код надо доделать...а если он не рабочий — поди выясни нормально причину ошибки — только факт известен.
На счет применения assert при сдаче в release — считаю, что всегда нужно корректно завершать работу приложения, а abort — он и в Африке аборт — приложение "уйдет по-английски".
Здравствуйте, omka, Вы писали:
O>Здравствуйте, MaximE, Вы писали:
>>> Если после ошибки есть возможность восстановиться, то throw, если нет, то abort().
O>Так если выше не перехватывать исключение, то обработка его по-умолчанию приведет к abort.
Верно.
Есть ситуации, когда известно, что это критический функционал, если он не работает, только abort() имеет смысл. Если бросать в этом случае исключение, читающий код может подумать, что можно восстановаться, поймав исключение, т.е. кинув исключение в таком случае я не точно передаю смысл моих намерений.
[]
O>На счет применения assert при сдаче в release — считаю, что всегда нужно корректно завершать работу приложения, а abort — он и в Африке аборт — приложение "уйдет по-английски".
Это может быть верно для гуи приложение. Для серверов мне ближе такой подход:
Rule of Repair: Repair what you can — but when you must fail, fail noisily and as soon as possible.
Software should be transparent in the way that it fails, as well as in normal operation. It's best when software can cope with unexpected conditions by adapting to them, but the worst kinds of bugs are those in which the repair doesn't succeed and the problem quietly causes corruption that doesn't show up until much later.
Therefore, write your software to cope with incorrect inputs and its own execution errors as gracefully as possible. But when it cannot, make it fail in a way that makes diagnosis of the problem as easy as possible.
Consider also Postel's Prescription:[10] “Be liberal in what you accept, and conservative in what you send”. Postel was speaking of network service programs, but the underlying idea is more general. Well-designed programs cooperate with other programs by making as much sense as they can from ill-formed inputs; they either fail noisily or pass strictly clean and correct data to the next program in the chain.
However, heed also this warning:
The original HTML documents recommended “be generous in what you accept”, and it has bedeviled us ever since because each browser accepts a different superset of the specifications. It is the specifications that should be generous, not their interpretation.
-- Doug McIlroy
McIlroy adjures us to design for generosity rather than compensating for inadequate standards with permissive implementations. Otherwise, as he rightly points out, it's all too easy to end up in tag soup.
Здравствуйте, MaximE, Вы писали:
ME>Верно.
ME>Есть ситуации, когда известно, что это критический функционал, если он не работает, только abort() имеет смысл. Если бросать в этом случае исключение, читающий код может подумать, что можно восстановаться, поймав исключение, т.е. кинув исключение в таком случае я не точно передаю смысл моих намерений.
Так надо кинуть исключение, которое точно бы передало смысл намерений.
И потом — обработка исключений полностью лежит на том, кто использует Ваш класс.
Можно в документации указать какая причина вызывает это исключение в коде, и рекомендации по его обработке, или вопрос в том, чтобы по-меньше положить работы на плечи пользователей класса?
omka wrote: > Так надо кинуть исключение, которое точно бы передало смысл намерений.
Вот мы обнаружили повреждение строки (например, str[str.size()]!=0). Что
делать?
Имеем поврежденный блок памяти, обнаружить повреждение обычно нельзя.
Исключение тоже кинуть нельзя — стэк может быть разрушен.
Поэтому лучше всего в такой ситуации записать core dump и не делать вид,
что ничего не случилось.
Здравствуйте, Cyberax, Вы писали:
C>Вот мы обнаружили повреждение строки (например, str[str.size()]!=0). Что C>делать?
C>Имеем поврежденный блок памяти, обнаружить повреждение обычно нельзя. C>Исключение тоже кинуть нельзя — стэк может быть разрушен.
C>Поэтому лучше всего в такой ситуации записать core dump и не делать вид, C>что ничего не случилось.
Ну, механизм исключений делался не для того, чтобы делать вид, что ничего не случилось — а локализовать место возникновения ошибки для принятия решения о дальнейшей ходе работы.
В подобном случае именно в точке возникновения ошибки видно, что дальнейшая работа приложения недопустима — не зачем генерировать исключение — это верно.
"Кинуть исключение, которое точно бы передало смысл намерени" — я имел ввиду не на постой кидать исключения, а там, где это нужно.
"На счет применения assert при сдаче в release — считаю, что всегда нужно корректно завершать работу приложения" — может core dump это как раз и есть корректное завершение работы — для системы и самого приложения завершение приложения — самый безопасный выход.
Здравствуйте, omka, Вы писали:
O>Ну, механизм исключений делался не для того, чтобы делать вид, что ничего не случилось — а локализовать место возникновения ошибки для принятия решения о дальнейшей ходе работы.
Не согласен. Предназначен он для простой передачи ошибки от уровня, где ошибка произошла, уровню, который готов эту ошибку обработать. Который о коде, кинувшем исключение, по хорошему вообще не знает.