добрый день! постепенно прививаю себе одну полезную фичу С++ за другой, как только с ней разберусь. настал черед и assert(), но все никак не могу до конца понять, каким образом assert() действует в _не_ дебуг версии откомпиленной программы? насколько я понимаю (могу ошибаться, поправьте пожалуйста если это так), код макроса assert() включается только в дебуг версию приложения, и в случае невыполнения условия в assert-e происходит корректное завершение программы. если это все верно, то как assert помогает в релиз-версиях программы? допустим, есть след. кусок кода: Код (Text): inline void Array::Elem(int i) { assert(i>=0 && i<len); return val[i]; } как эта вставка assert в этом методе поможет корректному отрабатыванию этого метода в релиз версии программы? поясните, кому не сильно долго
в релиз-версии никак, в дебаг-версии прога будет брякаться по int 3 асерты обычно ставят в тех местах, куда входящие данные не передаются извне, и где впринципе ни при каких обстоятельствах не может быть исключений
Cr4sh, понятно. но меня смущает вот эта выдержка из "man assert": получается, что этот макрос может быть удален во время компиляции, но не обязан --> этот макрос может присутствовать в релиз вершн программы. и вообще, тон этой выдержки какбы говорит о том, что по-дефолту этот макрос не удаляется во время компиляции. или я не так интерпретирую эту выдержку? и если в релиз вершне этот макрос никак не проявляется, то зачем же его юзать? чтобы отловить бОльшую часть потенциальных багов в дебуг вершне и надеяться что далее в релизе их уже не будет? обратимся к куску кода в посте#1. почему программист может спать спокойно, включив эту строчку с ассертом в этот метод выше? ведь в релиз вершне ассерта уже не будет, и следовательно, запрошенный по индексу элемент массива не факт что будет удовлетворять границам массива, и будет серьезный баг. что на этот счет можете сказать? спасибо!.
Собственно, в справке всё сказано: Как работает — посмотри сорцы и в отладчике. Или тебе неясен сам макрос? Наоборот, возникает исключительная ситуация вследствие нарушения утверждения (assert'a) и показывается соответствующее окошко. При нажатии на кнопку "Повторить" подключается отладчик и можно работать с ним. Утверждения помогают только при отладке, в релизе их нет. Для последнего есть макрос VERIFY, но использовать его надо с умом, а лучше делать свои проверки и корректное завершение операций в случае нарушения их. Так. Просто надо помнить, что отладочные средства — это не панацея.
IceStudent, а что это за справка? только не говорите что это из MSDN, у меня нету Виндовс. окей, с дебуг-вершн теперь прояснилось, спасибо вам, IceStudent. осталось разобраться с релиз-вершн. процитирую самого себя: или же правильнее написать что-то типа: Код (Text): inline void Array::Elem(int i) { assert(i>=0 && i<len); if ( i <= 0 || i > len ) //прописали проверку на границы явно return; return val[i]; } для того чтобы не беспокоиться за выход за границы в массиве в релиз-вершн программы?
А еще можно определить такой макрос assert(): Код (Text): #define STATIC_ASSERT(X) extern int _ass_ert_[ ( (X) != 0 ) * 2 - 1 ]; Он будет валиден для проверок времени трансляции. Тоесть например, для сравнения типов и размерности структур/массивов. Имя _ass_ert_(в данном случае) также часто завязывают на всякие компайлер-зависимые рендомайзеры, вроде __LINE__, __FILE__ и т.д., дабы исключить их возможное повторное появление в большом проекте.
mathio А можно чуть подробнее про вышеприведённый макрос, желательно с парой примеров, а то я что-то подвис на фразе "для сравнения типов".
Правильнее, "размерности" типов, my mistake Ну, а примеров всяких до кучи можно привести Код (Text): typedef struct { int a; char b; short c; } aaa; typedef struct { int a; char b; int c; } bbb; aaa _a; bbb _b; STATIC_ASSERT(sizeof(_a) == sizeof(_b)) или Код (Text): #pragma pack(push, 1) typedef struct { int a; char b; short c; } aaa2; #pragma pack(pop) #pragma pack(push, 8) typedef struct { int a; char b; short c; } aaa3; #pragma pack(pop) aaa2 _a2; aaa3 _a3; STATIC_ASSERT(sizeof(_a2) == sizeof(_a3))
censored, да, верно. я сначала неправильно написал. IceStudent, раз мы явно прописываем проверку в теле ф-ции-члена, то почему вот в этой теме ,напротив, дали мне понять, что ошибки нет? хочу все по полочкам расставить, because i am curious
varnie Во-первых, никто не заставляет делать проверки и её отсутствие не является ошибкой. Но качество софта будет на твоей совести. Во-вторых, есть различие между написанием кода для библиотеки и непосредственно программы, и различие заключается в контексте. В библиотеке желательно проверять все входные данные и корректно их обрабатывать с тем, чтобы не нарушить нормальную работу программы. В данном случае реализованы два метода: быстрый без проверки и "медленный", но с проверкой. Это документировано и ответственность за корректность индекса при быстром доступе к элементам ложится на прикладной код, использующий библиотеку. Применительно к #5 можно сделать следующий вывод: если известно, что входные данные корректны (их проверка есть выше явно либо в виде условия цикла (for(; i < len), то нет смысла делать ещё одну проверку.