Здравствуйте, Pavel Dvorkin, Вы писали:
PD>1.Не сотвори себе кумира!
мы ведь говорили про принцип KISS? вот у меня есть предположение, что люди, которые стояли у истоков Юникс, знают намного больше нас с тобой о его точном значении
PD>2. Не относись ко всему чересчур серьезно. Имей чувство юмора.
имею. каждый день
PD>А почему он глохнуть-то должен ? Можно ить обычных размеров сделать, и с обычным расходом горючего. Тойота вроде не глохнет, и Мерседес тоже. И размерами они не с ТУ-154. PD>А вот если у вас только Запорожец получается, то научитесь делать хотя бы Тойоту. Но обычных размеров.
мы ведь говорим о программах, а не о машинах?
а вот как раз они глохнут. и "взрываются". причем регулярно
поэтому давайте сделаем сначала то, что будет нормально ездить и возить грузы. Пусть и не очень быстро, зато с гарантированной доставкой из точки А в точку Б. Причем в целом и непритронутом виде.
PD>Нет. Зачем мне про него забыть — он примерно на 1000 компьютеров работает в моем коде, и пока никто не жаловался и не будет — потому как не может быть там никакой проблемы.
многие так думали. пока жареный петух в одно место не клюнул
PD>А кстати, о sprintf. Меня, как я помню, обвиняли в том. что возможно переполнение буфера. Не спорю, теоретически возможно. Но ведь и в этом операторе переполнение возможно
PD>int nScreenArea = nScreenWidth * nScreenHeight;
PD>А вдруг у нас будет экран 80000*60000. Сразу все перестанет работать.
PD>Так вот, мой sprintf вызовет переполнение буфера. Обязательно вызовет. Но не раньше, чем этот пример сгенерирует integer overflow
разница в том, что этот код не вызовет порчу стека. а sprintf — вызовет
улавливаешь разницу?
кстати говоря, во многих серьезных конторах за использование любой функции из семейства printf нещадно бьют по рукам. И даже более серьезно — по кошельку.
Здравствуйте, Дарней, Вы писали:
Д>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>1.Не сотвори себе кумира!
Д>мы ведь говорили про принцип KISS? вот у меня есть предположение, что люди, которые стояли у истоков Юникс, знают намного больше нас с тобой о его точном значении
Не понял. Или ты имеешь в виду, что я неправильно расшифровал аббревиатуру ?
Д>мы ведь говорим о программах, а не о машинах? Д>а вот как раз они глохнут. и "взрываются". причем регулярно
Не без этого, не спорю. Но бороться за то, чтобы этого не было, надо с соразмерными затратами. Если, конечно, речь не идет о программе управления ядерным реактором. Если ICQ раз в месяц падает, то еще вопрос — нужна ли мне ICQ, которая падает раз в 3 месяца и жрет памяти в 3 раза больше.
Д>поэтому давайте сделаем сначала то, что будет нормально ездить и возить грузы. Пусть и не очень быстро, зато с гарантированной доставкой из точки А в точку Б. Причем в целом и непритронутом виде.
Нет, не пойдет. Потому что если с меня за эту поездку на самоновейшем самолете возьмут из Омска в Москву $1000, я предпочту обычный российский поезд, который довезет меня за $100, хотя, возможно, слегка опоздает. Кстати, и риск аварии там не больше, чем у самоновейшего самолета.
А программ без ошибок — не бывает. Вспомни
"Программа, свободная от ошибок, есть абстрактное теоретическое понятие".
Д>многие так думали. пока жареный петух в одно место не клюнул
Ну несерьезно это. Есть страна, для которой я это делал. Есть у них в стране некая информация (извини, но деталей рассказывать не буду). Эта информация там появилпась, когда еще никаких компьютеров на свете не было, а может, и автомобилей не было. И вот я эту информацию в некий буфер заношу. И то, что она никак не может быть больше, чем 500 символов — гарантия в 101%. Никогда не может, ну так же, как имя русское не может быть длиной в 500 символов. А времени считать эту длину абсолютно нет, потому как на все про все мне дано 100 мсек. И в этих условиях ты все же будешь утверждать, что buffer overrun возможен ?
Д>разница в том, что этот код не вызовет порчу стека. а sprintf — вызовет Д>улавливаешь разницу?
Нет, не улавливаю. все равно это кончится неверным поведением программы и в конце концов крахом. Причем скорее всего не здесь, а где-то еще. Так что разницы я не улавливаю. Или ты хочешь сказать, что buffer overrun — это намного хуже, чем integer overflow ? По мне, один черт — все равно дальше ничего хорошего не будет.
На тебе, пожалуйста
int nScreenArea = nScreenWidth * nScreenHeight;
int nSquareLength = sqrt(nScreenArea); // а какого бы размера был квадратный дисплей с таким же числом пикселей ?
и получи sqrt domain error (не помню, как он сейчас называется правильно) — корень из отрицательного числа.
Д>кстати говоря, во многих серьезных конторах за использование любой функции из семейства printf нещадно бьют по рукам. И даже более серьезно — по кошельку.
А это от ситуации зависит. В том проекте, в котором я участвовал, мне все было разрешено, кроме одного — низкой скорости работы. Занял бы на диске лишний Гбайт — простили бы. ОП использовал бы в 2 раза больше, чем надо — тоже простили бы. А вот уложиться я должен был в 100 мсек. Кровь из носу. Потому что если 200 мсек займет — это кончится просто тем, что данный образец будет снят с обработки по нехватке времени, а тем самым число необработанных образцов увеличится. А обрабатывается таких образцов в день примерно 30,000 только на одной машине, и на каждый образец дается не более 3 сек. И за это время к моему ПО делается 10-15 запросов плюс, естественно, то время, которое нужно на оставшуюся часть, а оно есть примерно 60% общего времени. А машин примерно 1000. Борьба шла за каждый процент. И мне все прощалось, только бы быстрее. И сделал я им вместо 100 мсек 20-30 мсек, и были они в полном восторге
А лишних Гбайтов я , кстати, не использовал. И лишней ОП — тоже. Ну разве что самую малость — буфер там был один с запасом в 64 Кбайта
Здравствуйте, Pavel Dvorkin, Вы писали:
Д>>кстати говоря, во многих серьезных конторах за использование любой функции из семейства printf нещадно бьют по рукам. И даже более серьезно — по кошельку.
PD>А это от ситуации зависит. В том проекте, в котором я участвовал, мне все было разрешено, кроме одного — низкой скорости работы. Занял бы на диске лишний Гбайт — простили бы. ОП использовал бы в 2 раза больше, чем надо — тоже простили бы. А вот уложиться я должен был в 100 мсек. Кровь из носу. Потому что если 200 мсек займет — это кончится просто тем, что данный образец будет снят с обработки по нехватке времени, а тем самым число необработанных образцов увеличится. А обрабатывается таких образцов в день примерно 30,000 только на одной машине, и на каждый образец дается не более 3 сек. И за это время к моему ПО делается 10-15 запросов плюс, естественно, то время, которое нужно на оставшуюся часть, а оно есть примерно 60% общего времени. А машин примерно 1000. Борьба шла за каждый процент. И мне все прощалось, только бы быстрее. И сделал я им вместо 100 мсек 20-30 мсек, и были они в полном восторге
PD>А лишних Гбайтов я , кстати, не использовал. И лишней ОП — тоже. Ну разве что самую малость — буфер там был один с запасом в 64 Кбайта
Зато как же обломно после таких проектов формочки на JSP рисовать и SQL запросы сочинять!
Блин, словами не передать.
Зато антураж какой! Рефакторинг, юниттестинг, код ревью, баг трекинг, UML, XML, SQL,... память нынче не ресурс... давай, давай, сроки горят... память нынче не ресурс... давай, давай, все должно было работать еще вчера... память нынче не ресурс... Об эффективности программ
Здравствуйте, Pavel Dvorkin, Вы писали:
Д>>мы ведь говорили про принцип KISS? вот у меня есть предположение, что люди, которые стояли у истоков Юникс, знают намного больше нас с тобой о его точном значении
PD>Не понял. Или ты имеешь в виду, что я неправильно расшифровал аббревиатуру ?
расшфировал аббревиатуру — правильно. Понял смысл — неправильно.
Не вижу вообще смысла спорить на эту тему. Есть общепринятое значение, которое вкладывается в это выражение. А если ты решил для себя, что будешь называть стол стулом — то это исключительно твои частные проблемы.
PD>Не без этого, не спорю. Но бороться за то, чтобы этого не было, надо с соразмерными затратами. Если, конечно, речь не идет о программе управления ядерным реактором. Если ICQ раз в месяц падает, то еще вопрос — нужна ли мне ICQ, которая падает раз в 3 месяца и жрет памяти в 3 раза больше.
раз в месяц? да вы, батенька, оптимист
PD>Нет, не пойдет. Потому что если с меня за эту поездку на самоновейшем самолете возьмут из Омска в Москву $1000, я предпочту обычный российский поезд, который довезет меня за $100, хотя, возможно, слегка опоздает. Кстати, и риск аварии там не больше, чем у самоновейшего самолета.
вооот! о чем я собственно и говорил
"самоновейший самолет" — это как раз твое гипотетическое быстрое и надежное ПО
медленный поезд — это то тормозное, но работающее ПО, которое есть сейчас
PD>Ну несерьезно это. Есть страна, для которой я это делал. Есть у них в стране некая информация (извини, но деталей рассказывать не буду). Эта информация там появилпась, когда еще никаких компьютеров на свете не было, а может, и автомобилей не было. И вот я эту информацию в некий буфер заношу. И то, что она никак не может быть больше, чем 500 символов — гарантия в 101%. Никогда не может, ну так же, как имя русское не может быть длиной в 500 символов. А времени считать эту длину абсолютно нет, потому как на все про все мне дано 100 мсек. И в этих условиях ты все же будешь утверждать, что buffer overrun возможен ?
сразу вспоминается случай, когда разработчики решили, что длина серии паспорта не может быть больше 10 символов (может быть и не десять, не помню точно)
А потом приехал парень из страны, где серия паспорта имела больше символов. И бедолага несколько месяцев ходил по инстанциям.
еще могу напомнить про случай, когда разработчики решили "ну не может эта переменная переполниться! ни никак! потому что этого не может быть никогда!"
а потом в траекторию полета внесли изменения, и аппарат с треском рухнул.
PD>Нет, не улавливаю. все равно это кончится неверным поведением программы и в конце концов крахом. Причем скорее всего не здесь, а где-то еще. Так что разницы я не улавливаю. Или ты хочешь сказать, что buffer overrun — это намного хуже, чем integer overflow ? По мне, один черт — все равно дальше ничего хорошего не будет.
намного, намного хуже. А ты не догадываешься, почему?
в той ветке вроде бы вполне доходчиво объяснили
PD>А это от ситуации зависит. В том проекте, в котором я участвовал, мне все было разрешено, кроме одного — низкой скорости работы. Занял бы на диске лишний Гбайт — простили бы. ОП использовал бы в 2 раза больше, чем надо — тоже простили бы. А вот уложиться я должен был в 100 мсек. Кровь из носу. Потому что если 200 мсек займет — это кончится просто тем, что данный образец будет снят с обработки по нехватке времени, а тем самым число необработанных образцов увеличится. А обрабатывается таких образцов в день примерно 30,000 только на одной машине, и на каждый образец дается не более 3 сек. И за это время к моему ПО делается 10-15 запросов плюс, естественно, то время, которое нужно на оставшуюся часть, а оно есть примерно 60% общего времени. А машин примерно 1000. Борьба шла за каждый процент. И мне все прощалось, только бы быстрее. И сделал я им вместо 100 мсек 20-30 мсек, и были они в полном восторге
PD>А лишних Гбайтов я , кстати, не использовал. И лишней ОП — тоже. Ну разве что самую малость — буфер там был один с запасом в 64 Кбайта
и зря. Вполне возможно, что это позволило бы поднять скорость без ущерба для надежности.
Здравствуйте, eao197, Вы писали:
E>Зато как же обломно после таких проектов формочки на JSP рисовать и SQL запросы сочинять! E>Блин, словами не передать. E>Зато антураж какой! Рефакторинг, юниттестинг, код ревью, баг трекинг, UML, XML, SQL,... память нынче не ресурс... давай, давай, сроки горят... память нынче не ресурс... давай, давай, все должно было работать еще вчера... память нынче не ресурс... Об эффективности программ
Здравствуйте, Pavel Dvorkin, Вы писали: PD>А кстати, о sprintf. Меня, как я помню, обвиняли в том. что возможно переполнение буфера. Не спорю, теоретически возможно. Но ведь и в этом операторе переполнение возможно PD>int nScreenArea = nScreenWidth * nScreenHeight;
Угу. Именно поэтому при дефолтных настройках компилятора C# такой код вызовет у тебя compile-time error.
А если ты попробуешь схитрить, и сделать, к примеру, вот так:
private int GetScreenArea(int w, int h)
{
return w*h;
}
,а в рантайме скормить свои суперпикселы в этот метод, то произойдет OverflowException. Никакой попытки сохранить отрицательное число для будущего использования не будет.
Впрочем, для тех, кто экономит такты, можно сделать и вот так:
// все пользователи этого метода торжественно клянуться
// передавать достаточно маленькие значения w и h!private int GetScreenArea(int w, int h)
{
return unchecked(w*h);
}
PD>Так вот, мой sprintf вызовет переполнение буфера. Обязательно вызовет. Но не раньше, чем этот пример сгенерирует integer overflow
Сгенерирует. Но, в отличие от переполнения буфера, у нас есть детерминированное поведение системы. А не Undefined Behavior, который в некоторых особенно злостных случаях дефайнят за нас злые хакеры, причем таким образом, что эта дефиниция приносит нам заметный ущерб. Не помнишь червячка под MS SQL, который года три назад положил полмира?
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, srggal, Вы писали:
S>Так вот во Франции гдн-то в средние века проверяли жениха ( в приличных домах дворянского сословия ), претенденту подавали спелый персик, который он должен был съесть именно фруктовой вилкой и ножом, не теряя собственного достоинства, и непринужденно ведя светскую беседу с будующими родственниками.
В "приличных домах дворянского сословия" людям больше нечем заняться, кроме как заботиться о "сохранении своего достоинства". Потому что работают за них другие. Вот они и придумывали специальные вилки для фруктов, специальные вилки для рыбы и правила, как всё это дело следует употреблять (и не дай бог кому-то взять не ту вилку — фи, как некультурно!).
Нормальные же люди едят так, чтобы было удобно, а не чтобы произвести впечатление на окружающих.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Pavel Dvorkin, Вы писали: PD>>А кстати, о sprintf. Меня, как я помню, обвиняли в том. что возможно переполнение буфера. Не спорю, теоретически возможно. Но ведь и в этом операторе переполнение возможно PD>>int nScreenArea = nScreenWidth * nScreenHeight; S>Угу. Именно поэтому при дефолтных настройках компилятора C# такой код вызовет у тебя compile-time error.
Я что-то не понял
static void Main(string[] args)
{
int nScreenWidth = 80000, nScreenHeight = 60000;
int nScreenArea = nScreenWidth * nScreenHeight;
}
Настройки не менял. Компилируется. Запускается. Дает неверный результат — 505032704.
Вот в таком виде дает exception
int nScreenWidth = 80000, nScreenHeight = 60000;
int nScreenArea;
checked
{
nScreenArea = nScreenWidth * nScreenHeight;
}
Т.е по умолчанию uncheked.
Или у меня с настройками что-то не то (вроде не трогал) ?
S>А если ты попробуешь схитрить, и сделать, к примеру, вот так: S>
S>private int GetScreenArea(int w, int h)
S>{
S> return w*h;
S>}
S>
S>,а в рантайме скормить свои суперпикселы в этот метод, то произойдет OverflowException. Никакой попытки сохранить отрицательное число для будущего использования не будет.
Здравствуйте, Дарней, Вы писали:
E>>Зато как же обломно после таких проектов формочки на JSP рисовать и SQL запросы сочинять! E>>Блин, словами не передать. E>>Зато антураж какой! Рефакторинг, юниттестинг, код ревью, баг трекинг, UML, XML, SQL,... память нынче не ресурс... давай, давай, сроки горят... память нынче не ресурс... давай, давай, все должно было работать еще вчера... память нынче не ресурс... Об эффективности программ
Да нет проблем. Привыкать на начальном этапе сложновато. Да и за всем этим антуражем очень глубоко запрятано главное -- программа должна работать. А то, по моему опыту, очень многие любят говорить с придыханием разные умные слова (вроде "паттернов", "рефакторингов" и пр.), а работающего кода от них можно и не дождаться. В общем, мусора всякого и бесполезного шума слишком много. В АСУТП-шных задачах его как-то поменьше, может быть потому, что гораздо меньше людей этими задачами занимаются.
Да и не заниматься тоже не проблема. Мне не понравилось, я ушел. Но здесь во многом повезло -- случай хороший представился.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Я что-то не понял
Виноват. Действительно, если не сказать компилятору /checked+, то по умолчанию чекинг отключен. Тем не менее, обработка подобных ситуаций встроена как на уровне платформы (соответствующие команды MSIL), так и на уровне компилятора С# (ключевые слова checked, unchecked и ключ командной строки /checked). Что прекрасно соответствует принципам, заложенным в основу дотнета. Здесь значительно сложнее добиться UB.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Дарней, Вы писали:
Д>расшфировал аббревиатуру — правильно. Понял смысл — неправильно. Д>Не вижу вообще смысла спорить на эту тему. Есть общепринятое значение, которое вкладывается в это выражение. А если ты решил для себя, что будешь называть стол стулом — то это исключительно твои частные проблемы.
Допустим, что я понял это неправильно (хотя, честное слово, впервые об этом принципе я прочитал еще в 80-е годы, и в книге, которая к Unix не имела отношения. В таком случае будь добр объяснить, в чем неправильность моего понимания. Заявлять же — "ты неправ, и я не вижу смысла соприть на эту тему" — не есть аргумент.
Д>раз в месяц? да вы, батенька, оптимист
Нет, я ее просто не держу. . Поэтому статистики не знаю. Триллиан падал за несколько лет раз 5, и то обычно при Windows shutdown (что-то они там не учли, видимо)
PD>>Ну несерьезно это. Есть страна, для которой я это делал. Есть у них в стране некая информация (извини, но деталей рассказывать не буду). Эта информация там появилпась, когда еще никаких компьютеров на свете не было, а может, и автомобилей не было. И вот я эту информацию в некий буфер заношу. И то, что она никак не может быть больше, чем 500 символов — гарантия в 101%. Никогда не может, ну так же, как имя русское не может быть длиной в 500 символов. А времени считать эту длину абсолютно нет, потому как на все про все мне дано 100 мсек. И в этих условиях ты все же будешь утверждать, что buffer overrun возможен ?
Д>сразу вспоминается случай, когда разработчики решили, что длина серии паспорта не может быть больше 10 символов (может быть и не десять, не помню точно) Д>А потом приехал парень из страны, где серия паспорта имела больше символов. И бедолага несколько месяцев ходил по инстанциям.
Ну и что ? Это лишь говорит о том, что они неверно оценили максимальный размер, только и всего.
Программа делается для России. Приведи ситуацию, в которой здесь возможен buffer overrun. Фамилию и имя, please , в студию.
Д>еще могу напомнить про случай, когда разработчики решили "ну не может эта переменная переполниться! ни никак! потому что этого не может быть никогда!" Д>а потом в траекторию полета внесли изменения, и аппарат с треском рухнул.
Ну и что, опять-таки ? См. мой пример с nScreenArea. Может, оно когда-нибудь и грохнется, на 4ГПикс дисплее. Но не будешь же ставить под контроль все арифметические операции и на каждую из них писать try-catch из-за того, что при некорректно заданных операндах это может вызвать ошибку ? Или впрямь будешь писать везде так
int nScreenWidth = ..., nScreenHeight = ...;
int nScreenArea;
try
{
nScreenArea = nScreenWidth * nScreenHeight;
}
catch(...) {}
Если да — то неудивительно, что это будет работать очень медленно. А если нет — то при работе однажды произойдет unhandled exception, и аппарат рухнет.
Д>намного, намного хуже. А ты не догадываешься, почему?
Нет. Не догадываюсь. Потому что любая ошибка может привести к любой наведенной ошибке. А если ты хочешь сказать, что при этом будет неопределенное поведение — так и при неправильных результатах будет то же, не только при выходе индекса.
PD>>А лишних Гбайтов я , кстати, не использовал. И лишней ОП — тоже. Ну разве что самую малость — буфер там был один с запасом в 64 Кбайта
Д>и зря. Вполне возможно, что это позволило бы поднять скорость без ущерба для надежности.
Может , и позволило бы, вот тут я с тобой готов согласиться. Но мне просто не надо было. Ну не сидеть же мне и придумывать, где бы еще лишних 100 Мб израсходовать
А вообще основное различие между моей и твоей позицией ИМХО в том, что ты хорошо знаешь некоторые общепринятые принципы, но рассматриваешь их как догму, которую нельзя переступать, как сказал Sinclair, под страхом смертной казни. Я же считаю, что при определенных условиях может случиться так, что делать придется, нарушая многие общепринятые правила, если это нужно для решения задачи и другого выхода нет. В конце концов лучше написать работающую программу не по правилам, чем по правилам ничего не сделать.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Ну и что ? Это лишь говорит о том, что они неверно оценили максимальный размер, только и всего.
PD>Вот давай так
PD>char szTotal[500]; PD>sprintf(szTotal,"%s %s", szFirstName, szLastName);
PD>Программа делается для России. Приведи ситуацию, в которой здесь возможен buffer overrun. Фамилию и имя, please , в студию.
Очень просто. Этот код вызывается из обработчика веб формы регистрации пользователей. Злонамеренный пользователь вводит килобайт мусора. После чего твое CGI приложение делает core dump. Это называется уязвимость.
Еще более злонамеренный пользователь вводит килобайт специального мусора, и твое CGI приложение вносит нужные изменения в системные настройки, а уже потом делает core dump. Это называется эксплойт.
Продвинутый злонамеренный пользователь пишет плагин к известному сканеру сетей, который находит все инстансы твоего приложения в указанном IP — диапазоне.
Таоя компания попадает в списки рассылки "смертельно опасные уязвимости", и ее продукт попадает в черный список. Это называется "банкротство".
Дальше продолжать?
В таком сценарии оказывается значительно дешевле вовремя уволить того, кто использует подобный код, чем любая из альтернатив:
— оплачивать расходы от невовремя обнаруженной уязвимости
— нанять специальных людей, которые станут тестировать твою систему на предмет наличия подобных уязвимостей. PD>Ну и что, опять-таки ? См. мой пример с nScreenArea. Может, оно когда-нибудь и грохнется, на 4ГПикс дисплее.
Еще раз: то, как оно грохнется от целого переполнения, не приведет к исполнению постороннего кода. PD>Но не будешь же ставить под контроль все арифметические операции и на каждую из них писать try-catch из-за того, что при некорректно заданных операндах это может вызвать ошибку ?
Будешь, если тебе дорого твое место работы. Причем кэтчить все места тебе не потребуется: как только придет информация о том, что где-то твое приложение упало, ты получишь нормальный стек трейс, в котором ясно будет указано место падения.
Это позволит тебе очень быстро (по сравнению с анализом дампа) локализовать причины, и либо переписать код (например, используя long вместо int), либо вставить в нужных местах проверки (например там, где принимаются размеры). PD>Если да — то неудивительно, что это будет работать очень медленно. А если нет — то при работе однажды произойдет unhandled exception, и аппарат рухнет. PD>Нет. Не догадываюсь. Потому что любая ошибка может привести к любой наведенной ошибке. А если ты хочешь сказать, что при этом будет неопределенное поведение — так и при неправильных результатах будет то же, не только при выходе индекса.
Нет. Выброс исключения — это НЕ непределенное поведение. Это вполне определенное поведение, которое
PD>А вообще основное различие между моей и твоей позицией ИМХО в том, что ты хорошо знаешь некоторые общепринятые принципы, но рассматриваешь их как догму, которую нельзя переступать, как сказал Sinclair, под страхом смертной казни. Я же считаю, что при определенных условиях может случиться так, что делать придется, нарушая многие общепринятые правила, если это нужно для решения задачи и другого выхода нет. В конце концов лучше написать работающую программу не по правилам, чем по правилам ничего не сделать.
Ты не прав. Если влезть в исходники .Net, то можно увидеть и unsafe, и unchecked. Как раз для того, чтобы поднять производительность. Это не переступание догм, это подробное следование им. Потому, что отмененные такими опциями проверки делаются вручную. Сделать правильную программу быстрой легче, чем быструю — правильной.
Потому, что обо всех небыстростях тебе расскажет профайлер, а о неправильностях — пользователи и хакеры.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Допустим, что я понял это неправильно (хотя, честное слово, впервые об этом принципе я прочитал еще в 80-е годы, и в книге, которая к Unix не имела отношения. В таком случае будь добр объяснить, в чем неправильность моего понимания. Заявлять же — "ты неправ, и я не вижу смысла соприть на эту тему" — не есть аргумент.
Как я уже говорил, ведущие собаководы говорят — "читаемость и легкость расширения кода стоят превыше всего, в том числе и оптимальности по объему/производительности/любой иной"
отвечу заранее — нет, я не согласен с тем, что более простой код будет и более оптимальным. Совпадение одного с другим вполне возможно, но в большинстве случаев это вещи взаимоисключающие.
PD>Нет, я ее просто не держу. . Поэтому статистики не знаю. Триллиан падал за несколько лет раз 5, и то обычно при Windows shutdown (что-то они там не учли, видимо)
я тоже не держу — достала глюками и ненужными мне фичами, которые сжирают ресурсы. Поставил миранду — она у меня всего пару раз падала, но глючит все равно ничуть не меньше.
Д>>сразу вспоминается случай, когда разработчики решили, что длина серии паспорта не может быть больше 10 символов (может быть и не десять, не помню точно) Д>>А потом приехал парень из страны, где серия паспорта имела больше символов. И бедолага несколько месяцев ходил по инстанциям.
PD>Ну и что ? Это лишь говорит о том, что они неверно оценили максимальный размер, только и всего.
а они тоже думали, что оценили верно
PD>Вот давай так
PD>char szTotal[500]; PD>sprintf(szTotal,"%s %s", szFirstName, szLastName);
PD>Программа делается для России. Приведи ситуацию, в которой здесь возможен buffer overrun. Фамилию и имя, please , в студию.
фамилия очень простая — "Ивановвввввввввввввввввввввввввввввввв" (повторить нужное количество раз). Просто оператор заснул на клаве. Ах, такого не бывает, говоришь? Ну-ну.
Я уж не говорю о том, что это решение не только опасно, но еще и очень далеко от оптимума по производительности, которого тебе так сильно хотелось. Не догадываешься, почему? Рекомендую немного помедитировать над текстом sprintf
PD>Ну и что, опять-таки ? См. мой пример с nScreenArea. Может, оно когда-нибудь и грохнется, на 4ГПикс дисплее. Но не будешь же ставить под контроль все арифметические операции и на каждую из них писать try-catch из-за того, что при некорректно заданных операндах это может вызвать ошибку ? Или впрямь будешь писать везде так
как я уже говорил, твой пример к рассматриваемой ситуации с sprintf не имеет ни малейшего отношения. Поэтому смотреть тут особо и не на что.
PD>Нет. Не догадываюсь. Потому что любая ошибка может привести к любой наведенной ошибке. А если ты хочешь сказать, что при этом будет неопределенное поведение — так и при неправильных результатах будет то же, не только при выходе индекса.
разница в том, что ошибку переполнения можно обработать программно, ибо к порче сторонних данных она не ведет. Потертый стек — это однозначно полный трындец программе.
PD>А вообще основное различие между моей и твоей позицией ИМХО в том, что ты хорошо знаешь некоторые общепринятые принципы, но рассматриваешь их как догму, которую нельзя переступать, как сказал Sinclair, под страхом смертной казни. Я же считаю, что при определенных условиях может случиться так, что делать придется, нарушая многие общепринятые правила, если это нужно для решения задачи и другого выхода нет.
Эти самые "общепринятые принципы" были изучены мной на своей собственной шкуре, и на немаленьком количестве набитых шишек. Именно поэтому я говорю, что если ты вдруг подумал, что нужно нарушить один из них, потому что "это нужно для решения задачи и другого выхода нет" — значит, садись и думай еще раз.
Я в свое время тоже увлекался написанием мега-оптимизированных программ. Написал например для эксперимента дизассемблер для Z80, который целиком помещался в 1.5 килобайта. Но с тех пор я набил немало шишек, стал несколько мудрее и перестал заниматься подобной ерундой.
PD>В конце концов лучше написать работающую программу не по правилам, чем по правилам ничего не сделать.
А еще лучше — написать работающую программу, которая не будет использовать никаких грязных хаков. См также пример по sprintf выше
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>Я что-то не понял S>Виноват. Действительно, если не сказать компилятору /checked+, то по умолчанию чекинг отключен. Тем не менее, обработка подобных ситуаций встроена как на уровне платформы (соответствующие команды MSIL), так и на уровне компилятора С# (ключевые слова checked, unchecked и ключ командной строки /checked). Что прекрасно соответствует принципам, заложенным в основу дотнета. Здесь значительно сложнее добиться UB.
Так что же. вот лично ТЫ будешь встраивать мое вычисление площади в checked или нет ? Кстати, тем самым ты получишь только то, что программа вылетит из-за exception, а это хоть и не UB, но радости все равно мало. Формулирую жестче — ты будешь каждую операцию ставить под try-catch ?
Здравствуйте, Sinclair, Вы писали:
PD>>Программа делается для России. Приведи ситуацию, в которой здесь возможен buffer overrun. Фамилию и имя, please , в студию. S>Очень просто. Этот код вызывается из обработчика веб формы регистрации пользователей.
Этот код НЕ вызывается из обработчика ВЕБ-форм. В этом случае так писать действительно не стоит. Этот код берет проверенные значения из БД, где для их хранения НЕ ОТВЕДЕНО 500 char. По-прежнему будешь утверждать ?
Я же говорю — истина конкретна. Если данные не вызывают доверия — один разговор. Если они вызывают доверие — другой. В моей задаче — вызывали.
S>Еще раз: то, как оно грохнется от целого переполнения, не приведет к исполнению постороннего кода.
Еще раз — истина конретна.
S>Будешь, если тебе дорого твое место работы. Причем кэтчить все места тебе не потребуется: как только придет информация о том, что где-то твое приложение упало, ты получишь нормальный стек трейс, в котором ясно будет указано место падения.
Придет. Равно как и в Win32 это можно сделать — StackWalk64 и вообще Send Error Report
S>Это позволит тебе очень быстро (по сравнению с анализом дампа) локализовать причины, и либо переписать код (например, используя long вместо int), либо вставить в нужных местах проверки (например там, где принимаются размеры).
В общем, мы Вас не защищаем уже от багов, мы лишь обеспечиваем, чтобы Вы могли их найти, когда приложение рухнет
PD>>А вообще основное различие между моей и твоей позицией ИМХО в том, что ты хорошо знаешь некоторые общепринятые принципы, но рассматриваешь их как догму, которую нельзя переступать, как сказал Sinclair, под страхом смертной казни. Я же считаю, что при определенных условиях может случиться так, что делать придется, нарушая многие общепринятые правила, если это нужно для решения задачи и другого выхода нет. В конце концов лучше написать работающую программу не по правилам, чем по правилам ничего не сделать. S>Ты не прав. Если влезть в исходники .Net, то можно увидеть и unsafe, и unchecked. Как раз для того, чтобы поднять производительность. Это не переступание догм, это подробное следование им. Потому, что отмененные такими опциями проверки делаются вручную. Сделать правильную программу быстрой легче, чем быструю — правильной.
S>Потому, что обо всех небыстростях тебе расскажет профайлер, а о неправильностях — пользователи и хакеры.
ИМХО не стоит продолжать. Не договоримся. Разные позиции. Я готов с уважением относиться к твоей, но признавать ее как догму не могу.
Д>Как я уже говорил, ведущие собаководы говорят — "читаемость и легкость расширения кода стоят превыше всего, в том числе и оптимальности по объему/производительности/любой иной"
По второму кругу пойдем. Ведущие автомобилестроители говорят. что удобства разборки и сборки автомобиля важнее его характерстик.
Д>отвечу заранее — нет, я не согласен с тем, что более простой код будет и более оптимальным. Совпадение одного с другим вполне возможно, но в большинстве случаев это вещи взаимоисключающие.
И да, и нет... В большинстве — не согласен, а бывать — конечно, бывает.
PD>>Программа делается для России. Приведи ситуацию, в которой здесь возможен buffer overrun. Фамилию и имя, please , в студию.
Д>фамилия очень простая — "Ивановвввввввввввввввввввввввввввввввв" (повторить нужное количество раз). Просто оператор заснул на клаве. Ах, такого не бывает, говоришь?
Нет, не бывает. Потому как в моей задаче данные брались из SQL сервера, там попросту не могло быть такого — места нет.
Д>Я уж не говорю о том, что это решение не только опасно, но еще и очень далеко от оптимума по производительности, которого тебе так сильно хотелось. Не догадываешься, почему? Рекомендую немного помедитировать над текстом sprintf
А не надо медитировать. Я sprintf просто для примера привел. Реально у меня была ConcatenateStrings собственной разработки. Черт ее. sprintf, знает, как она там по форматам преобразует
Д>как я уже говорил, твой пример к рассматриваемой ситуации с sprintf не имеет ни малейшего отношения. Поэтому смотреть тут особо и не на что.
Ну не на что так не на что.
Д>разница в том, что ошибку переполнения можно обработать программно, ибо к порче сторонних данных она не ведет. Потертый стек — это однозначно полный трындец программе.
Ну и ставь себе try-catch на каждый оператор. Не много их найдется, которые в принципе не могли бы ошибку сгенерировать.
Д>Эти самые "общепринятые принципы" были изучены мной на своей собственной шкуре, и на немаленьком количестве набитых шишек. Именно поэтому я говорю, что если ты вдруг подумал, что нужно нарушить один из них, потому что "это нужно для решения задачи и другого выхода нет" — значит, садись и думай еще раз.
Да зачем мне об этом опять думать ? Проект этот я давно сдал, он и сейчас там работает, и будет еще бог знает сколько времени работать, и жалоб не было, хотя обработаны миллионы, если не десятки миллионов образцов, так что уж давно бы баг проявился бы
Д>Я в свое время тоже увлекался написанием мега-оптимизированных программ. Написал например для эксперимента дизассемблер для Z80, который целиком помещался в 1.5 килобайта. Но с тех пор я набил немало шишек, стал несколько мудрее и перестал заниматься подобной ерундой.
Ну и на здоровье. Я все равно придерживаюсь той точки зрения, что лучше сделать с нарушением правил, чем по правилам ничего не сделать.
Вот ответь прямо на вопрос. Тебе предлагается проект. К нему жесткие требования по времени работы, не уложишься — не примут. Написать со всеми твоими проверками — знаешь сам, что не уложишься. Но знаешь и, что если займешься "написанием мега-оптимизированных программ" — уложишься. Ядерным реактором это не управляет, самолеты не водит, крах если раз в месяц произойдет — не смертельно, перезапустят. Твои действия ?
PD>>В конце концов лучше написать работающую программу не по правилам, чем по правилам ничего не сделать.
Д>А еще лучше — написать работающую программу, которая не будет использовать никаких грязных хаков. См также пример по sprintf выше
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>По второму кругу пойдем. Ведущие автомобилестроители говорят. что удобства разборки и сборки автомобиля важнее его характерстик.
мы осбуждали смысл того выражения, или тенденции в работе ведущих автомобилестроителей?
PD>И да, и нет... В большинстве — не согласен, а бывать — конечно, бывает.
я бы еще добавил — очень редко бывает
Д>>фамилия очень простая — "Ивановвввввввввввввввввввввввввввввввв" (повторить нужное количество раз). Просто оператор заснул на клаве. Ах, такого не бывает, говоришь?
PD>Нет, не бывает. Потому как в моей задаче данные брались из SQL сервера, там попросту не могло быть такого — места нет.
А потом данные переводят с SQL сервера в другое хранилище, а твой код не трогают, потому что "он же раньше нормально работал"
тот зонд про который я говорил в предыдущем постинге как раз из-за этого упал
PD>А не надо медитировать. Я sprintf просто для примера привел. Реально у меня была ConcatenateStrings собственной разработки. Черт ее. sprintf, знает, как она там по форматам преобразует
без разницы. если она использует ASCIIZ строки — значит, она по определению не оптимальна
PD>Ну и ставь себе try-catch на каждый оператор. Не много их найдется, которые в принципе не могли бы ошибку сгенерировать.
а на хрена ставить на КАЖДЫЙ оператор? Ты вообще знаком с принципами обработки исключений?
PD>Да зачем мне об этом опять думать ? Проект этот я давно сдал
вот с этого и надо было начинать. Проект сдал, а что с ним потом будет — это уже дело десятое.
PD>Вот ответь прямо на вопрос. Тебе предлагается проект. К нему жесткие требования по времени работы, не уложишься — не примут. Написать со всеми твоими проверками — знаешь сам, что не уложишься. Но знаешь и, что если займешься "написанием мега-оптимизированных программ" — уложишься. Ядерным реактором это не управляет, самолеты не водит, крах если раз в месяц произойдет — не смертельно, перезапустят. Твои действия ?
Проект я буду писать так, чтобы удовлетворял всем условиям. Предварительно заложив в оценку дополнительное время на тестирование и всевозможные проверки. Ты доволен?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Sinclair, Вы писали:
PD>>>Программа делается для России. Приведи ситуацию, в которой здесь возможен buffer overrun. Фамилию и имя, please , в студию. S>>Очень просто. Этот код вызывается из обработчика веб формы регистрации пользователей.
PD>Этот код НЕ вызывается из обработчика ВЕБ-форм. В этом случае так писать действительно не стоит. Этот код берет проверенные значения из БД, где для их хранения НЕ ОТВЕДЕНО 500 char. По-прежнему будешь утверждать ?
А кто помешает dba сделать alter table через пару лет после запуска твоего приложения? Причем предыдущие два alter table прошли на ура.
Впрочем, речь не о том. Речь о том, что ты предлагаешь полагаться на то, что данные уже проверены каким-то сторонним способом. По умолчанию так делать нельзя. Такой метод обязан быть private. Он должен быть обложен всеми мыслимыми ассертами, и документация обязана содержать четкое упоминание о том, как его можно вызывать.
PD>В общем, мы Вас не защищаем уже от багов, мы лишь обеспечиваем, чтобы Вы могли их найти, когда приложение рухнет
А не существует никакого средства защитить от багов. Есть средство защитить от UB. PD>ИМХО не стоит продолжать. Не договоримся. Разные позиции. Я готов с уважением относиться к твоей, но признавать ее как догму не могу.
Личное дело каждого.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Pavel Dvorkin, Вы писали: PD>Так что же. вот лично ТЫ будешь встраивать мое вычисление площади в checked или нет ?
Если это код, который должен обеспечивать высокую надежность, то я просто скомпилирую его с /checked+. PD>Кстати, тем самым ты получишь только то, что программа вылетит из-за exception, а это хоть и не UB, но радости все равно мало.
Очень много. Вылет по exception — это детерминированное поведение. PD>Формулирую жестче — ты будешь каждую операцию ставить под try-catch ?
Нет конечно. А зачем? Что за бред? Сама идеология обработки исключений позволяет делать универсально применимый код. Я сделаю обработчик на достаточно высоком уровне, который попытается сделать что-то осмысленное.
И буду добавлять более низкоуровневые обработчики по мере необходимости.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
PD>>Ну и что ? Это лишь говорит о том, что они неверно оценили максимальный размер, только и всего.
PD>>Вот давай так
PD>>char szTotal[500]; PD>>sprintf(szTotal,"%s %s", szFirstName, szLastName);
PD>>Программа делается для России. Приведи ситуацию, в которой здесь возможен buffer overrun. Фамилию и имя, please , в студию. S>Очень просто. Этот код вызывается из обработчика веб формы регистрации пользователей. Злонамеренный пользователь вводит килобайт мусора. После чего твое CGI приложение делает core dump. Это называется уязвимость. S>Еще более злонамеренный пользователь вводит килобайт специального мусора, и твое CGI приложение вносит нужные изменения в системные настройки, а уже потом делает core dump. Это называется эксплойт. S>Продвинутый злонамеренный пользователь пишет плагин к известному сканеру сетей, который находит все инстансы твоего приложения в указанном IP — диапазоне. S>Таоя компания попадает в списки рассылки "смертельно опасные уязвимости", и ее продукт попадает в черный список. Это называется "банкротство".
Имхо, классики от программирования уже давно рекомендуют не доверять данным, приходящим к вам снаружи (а доверять только тем, что есть у вас в модуле, да и то с оглядкой). Тогда никаких страшилок с уязвимостями и эксплоитами можно не опасаться.
Что интересно, подобные проверки не лишены смысла и в управляемых средах.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.