Я иногда кое-что пишу или отлаживаю на Delphi или FreePascal (не только на них и вообще это не так важно). Сегодня отлаживал одну ошибку, программа почему-то падала. Выяснил, что падение возникает из-за ошибок в некоторых данных (это другая история), которые программа забывала проверить на корректность. Добавил проверку. Можно было бы успокоиться, что все заработало, но решил выяснить, из-за чего она все-таки падала при неправильных данных.
Это меня ошарашило. Я несмотря на то, что казалось бы имею давний опыт программирования на Delphi еще с 90-х годов и иногда периодически что-то писал, не знал, что exit внутри try...finally вызывает не немедленный выход из функции, а переход к блоку finally. Думал, что этот блок исполняется только в нормальном случае или при исключениях, а exit немедленно завершает функцию. Ошибался. Теперь удивляюсь, как же я умудрился раньше не нарваться на ошибки в этом месте (дважды вызов Free например из-за этого)
Мораль в качестве выводов:
1) Если есть ошибка полезно докопаться до ее истоков, а не просто избавиться от нее.
2) Можно обнаружить что-то для себя новое в казалось бы давно и хорошо известном.
Re: Как важно проверять в программах ошибки до конца
Здравствуйте, Michael7, Вы писали:
M>Это меня ошарашило. Я несмотря на то, что казалось бы имею давний опыт программирования на Delphi еще с 90-х годов и иногда периодически что-то писал, не знал, что exit внутри try...finally вызывает не немедленный выход из функции, а переход к блоку finally. Думал, что этот блок исполняется только в нормальном случае или при исключениях, а exit немедленно завершает функцию.
Не в качестве сарказма, а действительно любопытно — 2ALL: а где нибудь есть иное поведение?
И можно как нибудь вывернуться и это переопределить, скажем, на Java?
--
Спасибо
Re: Как важно проверять в программах ошибки до конца
Здравствуйте, Michael7, Вы писали:
M>Delphi еще с 90-х годов ... exit внутри try...finally
объясните идиоту, пожалуйста,
как можно использовать try...finally и не знать как оно работает?
Вы ведь где-то прочитали об исключениях, примеры учебные писали наверняка..
как так?
книжек под делфе не читали, в справку не заглядывали, а писали так же как на Turbo Pascal 7.0?
обработку исключений подсмотрели у соседа?
я не понимаю, правда....
это вне моего мировоззрения.
ненавижу все существующие ЯП
Re: Как важно проверять в программах ошибки до конца
Здравствуйте, Michael7, Вы писали:
M>Это меня ошарашило. Я несмотря на то, что казалось бы имею давний опыт программирования на Delphi еще с 90-х годов и иногда периодически что-то писал, не знал, что exit внутри try...finally вызывает не немедленный выход из функции, а переход к блоку finally.
программисты на дельфи — это всегда очень печальное зрелище. хуже только программисты на 1С
сорри, ниче личного, но это реально факт.
In P=NP we trust.
Re: Как важно проверять в программах ошибки до конца
Здравствуйте, newCL, Вы писали:
CL>Здравствуйте, Michael7, Вы писали:
M>>Delphi еще с 90-х годов ... exit внутри try...finally
CL>объясните идиоту, пожалуйста, CL>как можно использовать try...finally и не знать как оно работает?
Можно, как выяснил на своем опыте. В том и мораль, что можно оказывается чего-то не знать там, где давным давно, казалось бы все знал.
CL>Вы ведь где-то прочитали об исключениях, примеры учебные писали наверняка.. CL>как так?
Конечно. И это даже работает успешно, в конце-концов, не так часто exit использовал, кроме того, дублирование блока перед exit-ом далеко не всегда приводило к ошибкам. Анекдот, но так и есть.
CL>книжек под делфе не читали, в справку не заглядывали, а писали так же как на Turbo Pascal 7.0? CL>обработку исключений подсмотрели у соседа?
В книжке подробно описывалось как работают исключения, а вот о таком нюансе работы exit в старой еще 90-х годов книжке не было. Просто пропущен этот момент, а exit я знал еще действительно со времен турбо-паскаля. Затем казалось естественным, что он вызывает мгновенный выход.
Если бы я изучал Delphi с нуля и в 2000-х, возможно, что не оказался в заблуждении.
CL>я не понимаю, правда.... CL>это вне моего мировоззрения.
Я тоже не понимаю, теперь надо свой код везде пересмотреть
Re[2]: Как важно проверять в программах ошибки до конца
Здравствуйте, carpenter, Вы писали:
C>я както во фрискейле работал — так у них там с одной игрушкой типа волка ловящего яйца, C>гдето на 14 часу игры проскакивал глюк .
И?
Re[2]: Как важно проверять в программах ошибки до конца
Здравствуйте, carpenter, Вы писали:
C>я както во фрискейле работал — так у них там с одной игрушкой типа волка ловящего яйца, C>гдето на 14 часу игры проскакивал глюк .
вы все наверняка знаете что в микроокнтроллерных приложениях это рядовое явление, и отфиксить железку стоит серьезных трудозатрат
Мы не отступили, а изменили направление атаки!
Re[2]: Как важно проверять в программах ошибки до конца
D>программисты на дельфи — это всегда очень печальное зрелище. хуже только программисты на 1С
хотел поправить, но потом посмотрел сообщения — и не стал. не хочется бороться с такой страстью к обобщениям.
D>сорри, ниче личного, но это реально факт.
продолжайте плиз. человечество замерло в ожидании новых откровений.
Re[2]: Как важно проверять в программах ошибки до конца
Здравствуйте, djs_, Вы писали:
_>Здравствуйте, Michael7, Вы писали:
M>>Это меня ошарашило. Я несмотря на то, что казалось бы имею давний опыт программирования на Delphi еще с 90-х годов и иногда периодически что-то писал, не знал, что exit внутри try...finally вызывает не немедленный выход из функции, а переход к блоку finally. Думал, что этот блок исполняется только в нормальном случае или при исключениях, а exit немедленно завершает функцию.
_>Не в качестве сарказма, а действительно любопытно — 2ALL: а где нибудь есть иное поведение? _>И можно как нибудь вывернуться и это переопределить, скажем, на Java?
Да, можно. Написать System.exit(...);
Re[2]: Как важно проверять в программах ошибки до конца
Здравствуйте, Michael7, Вы писали:
M>Я иногда кое-что пишу или отлаживаю на Delphi или FreePascal (не только на них и вообще это не так важно). Сегодня отлаживал одну ошибку, программа почему-то падала. Выяснил, что падение возникает из-за ошибок в некоторых данных (это другая история), которые программа забывала проверить на корректность.
Вот чтобы подобной ерундой не заниматься, и были придуманы юнит-тесты.
Здравствуйте, Deprivator, Вы писали:
D>Здравствуйте, Michael7, Вы писали:
M>>Это меня ошарашило. Я несмотря на то, что казалось бы имею давний опыт программирования на Delphi еще с 90-х годов и иногда периодически что-то писал, не знал, что exit внутри try...finally вызывает не немедленный выход из функции, а переход к блоку finally.
D>программисты на дельфи — это всегда очень печальное зрелище. хуже только программисты на 1С D>сорри, ниче личного, но это реально факт.
Знаете, ничего личного, но, например, я, с высоты 11+-летнего опыта промышленной разработки на целой куче императивных языков, не вижу принципиальной разницы между дельфи, крестиками, джавой, шарпом, и чем-бы то ни было ещё императивным. В разных языках есть разные плюшки и фичи, иногда кажущиеся ненужными, но при этом, на самом деле, являющиеся весьма важными. Суть и стиль разработки всё равно не меняется. Не хочу начинать холивар, но дельфи — вполне нормальный императивный объектно-ориентированный язык. И довольно эффективный, учитывая мощь VCL, лёгкость клепания формочек, и офигенский RTTI. Другим компилируемым языкам до этого RTTI -- пахать и сеять. Другой вопрос, что сам факт использования exit() не говорит в пользу автора. Это, имхо, примерно как goto.
Re[2]: Как важно проверять в программах ошибки до конца
Здравствуйте, Michael7, Вы писали:
M>Это меня ошарашило. Я несмотря на то, что казалось бы имею давний опыт программирования на Delphi еще с 90-х годов и иногда периодически что-то писал, не знал, что exit внутри try...finally вызывает не немедленный выход из функции, а переход к блоку finally. Думал, что этот блок исполняется только в нормальном случае или при исключениях, а exit немедленно завершает функцию. Ошибался. Теперь удивляюсь, как же я умудрился раньше не нарваться на ошибки в этом месте (дважды вызов Free например из-за этого)
после второго курса любая прога на делфи начиналась у меня с {$O-}. Раз потратил вечер на понимание как в коде
for i:=0 to 7 do
...
i принимает значение 8, 9 и только потом выходит. А ответ прост как сало без хлеба: баг оптимизации.
If the message above is in English — means I'm wasting my work time and work computer to post here. No hard feelings
Re[3]: Как важно проверять в программах ошибки до конца
Здравствуйте, newCL, Вы писали:
L>>Вот чтобы подобной ерундой не заниматься, и были придуманы юнит-тесты.
CL>правильно, они придуманы чтоб другой ерундой заниматься.
Тем, для кого юнит-тесты эквивалентны занятию ерундой, срочно рекомендуется сменить профессию. На сантехника или там развозчика пиццы.
Других мнений по этому поводу быть не может.
Здравствуйте, landerhigh, Вы писали:
L>Здравствуйте, newCL, Вы писали:
L> для кого юнит-тесты эквивалентны занятию ерундой, срочно сменить профессию. L> Других мнений по этому поводу быть не может.
а вы тесты писали? насколько серьезно подходили к процессу их разработки? у вас была формальная модель, доказывающая корректность, непротиворечивость и полноту теста? сомнительно. и какая польза от теста, который что-то тестирует? конечно, польза есть, но если вы углубитесь в теорию и практику тестирования, то очень быстро убедитесь, что существуют и другие пути.
например, построив блок-схему можно визуализировать косяки и баги, которые хрен какой тест отловит. а что касается юнит-тестов, то у них столько ограничений, что лучше даже не начинать. и в условиях ограниченных ресурсов тесты не пишутся. представьте, что вы на экзамене. у вас пять задач и вы прикидываете, что времени хватает только на решение, но на проверку уже не остается. что вы будете делать? согласитесь, тут все зависит от сложности задач и вашей аккуратности. если вы не раздолбай и статистически вы ошибаетесь в одной задаче из десяти, то у вас хорошие шансы сдать по крайней мере четыре задачи, а то и все пять. а если проверка занимает больше времени, чем решение (а, обычно, это так и есть), то вы решите одну или две задачи и все скажут, что вы дурак. чистая математика, ничего личного.
в чем принципиальная разница:
а) программу запустили и она вроде как работает;
б) программа прошла все тесты, которые вы написали.
а принципиальной разницы и нет. программа прошла все тесты, вы ее запустили, а она взяла и упала. потому что если вы не можете написать программу без ошибок, то почему вы думаете, что ошибок не будет в тесте? они там будут. пример из жизни. знакомый писал тест для факториала. есть проверка на ноль, но нет проверки на отрицательные числа. нет проверки нецелых чисел (а для них тоже можно вычислить факториал). мой тест показал, что функция выдает некорректный результат как для отрицательных чисел так и для дробных. то есть юнит-тест ни хвоста не доказывал. потому что программист, который писал функцию факториала был не в курсе что такое факториал вообще и очень сильно удивился, когда _все_ калькуляторы считали факториалы дробных чисел. программист сказал, что они все идиоты и едут по встречной, а он находится в своем ряду.
вот и скажите мне какая польза от таких тестов? ведь если функция факториала написана с ошибкой потому что программист считает факториал только для целых чисел, то и тест функции факториала, написанный тем же программистом, тестирует факториалы только целых чисел. а если программист знает как считать факториалы для дробных чисел, то тут возникает другой вопрос -- с чем сверять результат? нужна эталонная функция факториала, а у нас ее нет (ну будем считать, что нет), а если обратиться к реальной жизни, где факториалы считаются приближенно, то даже при наличии эталонной функции очень сложно написать функцию для сравнения результатов -- это баг или мы все еще в рамках допустимой точности вычислений. допустим, эталонная функция ушла по максимуму вниз, а наша функция ушла по максимуму вверх. оба результата верны, но попытка их сравнения уже выходит за рамки приличия.
если вы не согласны и уверены в себе и своих знаниях -- плз, напишите функцию факториала вместе с тестом.
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Re[5]: Как важно проверять в программах ошибки до конца
Если никто не знает как это должно работать, ничего не поможет. Юниттесты скорее для другого: ловить случаи когда все работало и вдруг бац — сломалось.
Re[6]: Как важно проверять в программах ошибки до конца
Здравствуйте, linuz, Вы писали:
L>Если никто не знает как это должно работать, ничего не поможет. Юниттесты скорее для другого: ловить случаи когда все работало и вдруг бац — сломалось.
ок. factorial = gamma(n) + 1. если гамма считается приближенно, то factorial = gamma(n), но при этом 0! выдаст очень странный результат. допустим, в оригинале было factorial = gamma(n) + 1, кто-то убрал '+1'. юнит тест не проверял факторил нуля. и все типа работает. а потом -- бац! и кто-то передал в функцию ноль. чем поможет юнит-тест? а ничем.
или вот классический случай вычисления факториала через рекрусию:
int factorial(int n) {
return n == 0 ? 1 : n * factorial(n — 1);
}
передайте функции -1 и посмотрите, что произойдет.
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.