Пример был сделан так, чтобы даже PHP-шнику стало понятно, что исключения в Go есть, а не для того, чтобы показать, как надо писать. Паники специально были засунуты в дальний угол, но не всем дано такое понять.
управление выводом ошибки переместилось в run(), а вывод «Done» вообще пропал т.к. мы не знаем состояние
Всё, что у Вас пропало и переместилось, произошло не потому, что нельзя сделать как в 1-м случае, а потому что Вы так захотели. Не стоит делать выводы на таком основании. Ну а 1-й вариант на Go можете посмотреть в песочнице
Калькуляторы — это побочная продукция предприятия. Используются как программируемые контроллеры для приборов их же производства, востребованные одним заказчиком (или некоторыми).
Как известно, в рамках программы импортозамещения государственные ведомства обязаны заменять дорогие американские Windows и MS Office дешёвыми российскими аналогами
Я не путаю. В компиляторе нет неопределённых мест по природе программ на цифровых вычислительных устройствах(с поправкой на точность определения машинного языка). Неопределённость может быть только в спецификации. Вопрос лишь в том, как именно определяется поведение в компиляторе — наиболее разумным способом или абы как ради баллов в очках оптимизации, задано один раз или меняется от версии к версии. Unspecified же поведение как раз-таки определено на уровне стандарта, но подразумевает возможность выбора. В этом и суть названия, которое плохо передаётся на русском, — оно определено, но не специфицировано.
Компилятор видит, что в переменной r считается некоторая сумма. Переполнения переменной r произойти не должно. Иначе это неопределённое поведение, которое компилятор никак не должен рассматривать и учитывать.
Это, к сожалению, распространённое заблуждение, в которое, увы, верят и разработчики трансляторов. Поведение, не определённое в стандарте означает, что ответственность за его определение переносится с создателей стандарта на создателей транслятора. Это совсем не означает, что оно не должно учитываться, но именно так многие считают и распоряжаются своей отвественностью так, как Вы описали.
Претензия к компилятору вполне обоснована, но расчёт на то, что тут кто-то кому-то должен был бы наивен.
Тем не менее, прочувствовать правильный учёт ошибочной ситуации можно, включив опции -fsanitize=undefined -fsanitize-undefined-trap-on-error.
Наверно потому, что это ортогональные вещи. Опечатки могут приводить к ошибкам проверки, но злоумышленников интересует именно ошибки проверки вне зависимости от причины их происхождения, а не опечатки как таковые.
Воспроизводилось что? Во время отдыха я прочитал новость, посмотрел код, нашёл неточность, вырвал кусок, собрал, увидел результат, описал его под новостью. Собирать и тестировать NGINX и даже официально уведомлять об ошибке никогда не входило в мои планы.
Тут Andrey2008 постоянно борется с таким пренебрежительным отношением к ошибкам, но оно, очевидно, неискоренимо даже в среде ценителей.
Это практическая ошибка, проявляющаяся на gcc. И показатель качества — это только качество кода, а не реакция на уведомления. Реакция — это, всё же, о другом
Вы проигнорировали моё упоминание бесконечной истории. Я не искал специально ошибки в NGINX, а просто потянул ниточку новости — и понеслось. Ошибки в NGINX не досадная случайность, а закономерность, вызванная подходом к написанию кода. Это именно некачественный код рыхлых, переутяжелённых функций.
Вывод: где мы нашли меньше ошибок при написании статьи, там и код лучше :). Всё честно.
Давайте как пример рассмотрим NGINX, который Вы привели как пример качественного проекта, свидетельством чему было невыявление ошибок стат. анализом в 2014.
В 2017 вышла новость об устранении в нём уязвимости.
Я обратил внимание на то, как уязвимость была устранена:
Это было устранение возможного переполнения. Я решил проверить как выводятся start и end, ведь переполнения во время арифметических действий для проверки возможности переполнения других арифметических действий для меня не являются новостью.
Я увидел следующую картину:
Проверка с выходом из функции должна была предотвращать возможное переполнение целого со знаком start, но вместо такого сложения
start = start * 10 + (*p++ - '0');
было сделано такое
start = (start * 10 + *p++) - '0';
Что приводит к возможности переполнения левой части, а учитывая знаковость start, это является неопределённым поведением, что не даёт гарантию компенсации последующим вычитанием '0'. Тогда я даже смог добиться некорректного поведения при компиляции похожего куска кода с помощью gcc с оптимизацией.
Это всё ставило под удар конечное утверждение об исправлении уязвимости, так как эта цепочка при определённых обстоятельствах могла привести к некорректности проверки.
Я сообщил о своей находке и через некоторое проблема была исправлена. Это было отрадно, но сама заплатка снова дала повод задуматься. Подобный функционал был разбросан по множеству перегруженных кодом функций. Эти куски не могли быть обобщены в одну функцию, которая могла быть подвергнута тщательному осмотру и тестированию из-за обилия неструктурного кода, мешающего провести декомпозицию. При таком подходе к написанию кода остаётся только гадать, сколько похожего кода было не затронуто исправлением, так как его трудней выявить. Более того, я обнаружил ещё недостатки, но уже утратил желание в этом участвовать — это стало походить на бесконечную историю.
А теперь вопросы:
Способен ли подобные ошибки находить анализатор?
Насколько качественный код NGINX?
Насколько верно утверждение про связь невыявления ошибок стат.анализом и качеством?
Вы, действительно, предвзяты в статьях. Вот пример:
Если проект качественный, то мы пишем, что не смогли найти ошибок
Здесь содержится логическая ошибка. Вы предвзято связываете качество проекта с возможностью нахождения ошибок вашим инструментом, но это не так. Невозможность найти ошибки статическим анализатором слишком мало говорит о качестве и наоборот, что, естественно, не отменяет пользы от использования анализатора.
Даже в технических (точных) науках докторские бывают так себе, что уж творится в гуманитарных науках.
Такое пренебрежительное отношение сверху к «этим вот гуманитариям» постоянно встречается в среде программистов. Хотя с чего бы? Естественно возникшие языки и то, что с ними связано является несоизмеримо более сложной темой, чем языки программирования и то, что с ними связано.
А что насчёт этого?
Точно ли второй & должен быть с 0-й маской?
Всё, что у Вас пропало и переместилось, произошло не потому, что нельзя сделать как в 1-м случае, а потому что Вы так захотели. Не стоит делать выводы на таком основании. Ну а 1-й вариант на Go можете посмотреть в песочнице
Претензия к компилятору вполне обоснована, но расчёт на то, что тут кто-то кому-то должен был бы наивен.
Тем не менее, прочувствовать правильный учёт ошибочной ситуации можно, включив опции -fsanitize=undefined -fsanitize-undefined-trap-on-error.
Тут Andrey2008 постоянно борется с таким пренебрежительным отношением к ошибкам, но оно, очевидно, неискоренимо даже в среде ценителей.
В 2017 вышла новость об устранении в нём уязвимости.
Я обратил внимание на то, как уязвимость была устранена:
Это было устранение возможного переполнения. Я решил проверить как выводятся start и end, ведь переполнения во время арифметических действий для проверки возможности переполнения других арифметических действий для меня не являются новостью.
Я увидел следующую картину:
Проверка с выходом из функции должна была предотвращать возможное переполнение целого со знаком start, но вместо такого сложения
было сделано такое Что приводит к возможности переполнения левой части, а учитывая знаковость start, это является неопределённым поведением, что не даёт гарантию компенсации последующим вычитанием '0'. Тогда я даже смог добиться некорректного поведения при компиляции похожего куска кода с помощью gcc с оптимизацией.
Это всё ставило под удар конечное утверждение об исправлении уязвимости, так как эта цепочка при определённых обстоятельствах могла привести к некорректности проверки.
Я сообщил о своей находке и через некоторое проблема была исправлена. Это было отрадно, но сама заплатка снова дала повод задуматься. Подобный функционал был разбросан по множеству перегруженных кодом функций. Эти куски не могли быть обобщены в одну функцию, которая могла быть подвергнута тщательному осмотру и тестированию из-за обилия неструктурного кода, мешающего провести декомпозицию. При таком подходе к написанию кода остаётся только гадать, сколько похожего кода было не затронуто исправлением, так как его трудней выявить. Более того, я обнаружил ещё недостатки, но уже утратил желание в этом участвовать — это стало походить на бесконечную историю.
А теперь вопросы:
Здесь содержится логическая ошибка. Вы предвзято связываете качество проекта с возможностью нахождения ошибок вашим инструментом, но это не так. Невозможность найти ошибки статическим анализатором слишком мало говорит о качестве и наоборот, что, естественно, не отменяет пользы от использования анализатора.