Pull to refresh

Comments 164

Классический пример. Называется, ставьте фигурные скобки и не увлекайтесь goto.

Кроме того, слово fail в коде переводить не стоило, это метка.


Оригинал:
> Кроме того, слово fail в коде переводить не стоило, это метка.
Да уж, облом так облом :)
Нет, называется бекдор :)
Фигурные скобки и goto тут ни при чём. Во-первых, всё это вообще надо было писать по-другому, во-вторых, достаточно было бы просто взглянуть на код и увидеть, что два goto — это какая-то хрень. Установление фигурных скобочек бы не помогло, потому что очевидно, что в код просто не смотрели (специально).

Бекдоры и должны быть похожи на опечатки. Вспомните про баг в ядре линукса.
Не обязательно объяснять злым умыслом то, что может быть сделано по глупости. Например, в этой же функции есть signedHashes, который освобождается в конце, но нигде не используется (signedHashes.data = 0 не считаем).
Я не сторонник теорий заговоров, однако сходу не могу придумать сценарий, при котором в диффе в середине давно написанного кода появляется одинокая неверная строчка:

Большая часть изменений — банальный однообразный рефакторинг, а эта строка явно выделяется и бросается в глаза.

А с signedHashes ситуация вполне типичная: структура данных когда-то использовалась, но однажды логику переписали без неё, а инициализацию и освобождение убрать забыли. Это относительно часто встречается.
Вы меня прям заинтриговали. Я про опасности rebase аж 2 статьи писал, однако в этом случае не могу придумать, каким образом он может быть виноват. Всё равно ведь в каком-то коммите эту строку надо было написать поверх древнего кода.
Сначала строчку ошибочно стерли, потом дописали обратно. Первый коммит при интерактивном rebase был пропущен…
Будет конфликт. Т.к. в коммите будет «вставить goto между двумя строчками if», а там уже один goto находится.
Конфликта не будет, если строки идентичные, как в данном случае, просто смержится автоматически.
Попробуйте воспроизвести. Уверен, что не получится.
Я попробовал сам. Оказалось, что гит ведёт себя несколько умнее. Он определяет, что данная строка уже была добавлена, и удаляет её из накладываемого патча, применяя остальные изменения из коммита.

git clone https://gist.github.com/9168347.git
cd 9168347
git checkout -b rebase
git rebase -i 9d4ebb

pick 4e8b496 Some commit
#pick 142d7bf Removed goto
pick f2871e8 Returned goto

Successfully rebased and updated refs/heads/rebase.

В результате оригинальный коммит
@@ -1,6 +1,8 @@
 if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)
     goto fail;
 if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
+    goto fail;
 if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
     goto fail;
 
+

гит переделал в:
@@ -5,3 +5,4 @@
 if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
     goto fail;
 
+


Судя по всему, Вы именно это и имели в виду. :)
Появление дублирующихся строк при автоматическом merge в git'е я наблюдал на практике несколько раз. Конкретную причину не знаю, сильно не разбирался — просто исправлял. Возможно, связано с одним и тем же коммитом в нескольких ветках (исправление ошибки в разных версиях), которые потом залили в master.
Рискну предположить, что строки отличались символами окончания строки (\r\n против \n). Бывает, если не прописать настройки в вин-клиенте. В результате строки вроде бы идентичные, но не совсем, и поэтому не мержатся в одну.
У меня был забавный случай с CVS. Я добавил в структуру новых полей, а коллкга в это же время переименовал старые. CVS это смержил так, что в структуре появились и переименованные, и сохранились старые поля. Компилятор это прекрасно съел, и я несколько часов разбирался, почему все перестало работать.
Теория заговора тем и хороша, что ею можно объяснить, пожалуй, что угодно.
У вас, поди, и шапочка из фольги есть ;)
Не помогает!!! Кастрюлька лучше и роднее :)
О, да я теперь начальству за все свои косяки в программировании могу отмазаться — это не баг, это секретный бекдор.
Умерьте фантазию, бэкдор пускает не любого, а только того, кого надо.
«Кто надо» — это не секретный элитный клуб, а всего лишь тот, кто знает об этом бекдоре.
Когда участвовал в разработке кода для ядра FreeBSD приходилось соответствовать coding style, который запрещал фигурные скобки в однострочных if и for. И это вызывало ошибки даже у опытных программистов. Я так и не смог убедить руководство изменить coding style.
В родном коде ядра встречались перлы — if, потом 5 строк комментариев, котом один оператор. Читать сложновато, но весело.
Оставлю для истории. Ну как можно взять — и перевести часть исходника?

Ага, я выше уже выложил =)
И? Что значит сей минус?

Комментарий редактируется, как максимум, в течении трех минут после опубликования. Т. е. я и mayorovp выложили картинки почти одновременно (я лишь на минуту раньше). До редактирования в моем комментарии не было только картинок, но я решил добавить, т. к. после изменения поста многим будет неясно про что речь.
Возможно, человек, поставивший вам минус (это был не я), намекнул, что я и сам должен был увидеть ваш комментарий. Хотя бы потому что в момент публикации комментарии обновляются. А уж сторонний читатель никоим образом не сможет увидеть мой комментарий перед вашим. Таким образом, фраза «я выше уже выложил» не несет никакой информации и лишь сообщает всем очевидную вещь.
Вероятно. Как ни делай, параметр-который-нельзя-называть сливают в таких холиварных темах.
Да ладно вам, чего вы переживаете из-за одного минуса? Во многих случаях это не более, чем стат. погрешность. Возьмите недавний топик «Как айтишник по магазинам ходил» — к 769(!) плюсам нашлось 45 минусов. Не переживать же из-за каждого из них, так можно и все нервы пропереживать ;)
Из-за минусов обычно не переживают, а недоумевают.
Иногда просто очень непонятна реакция. Есть пара сливов, приблизится к пониманию причин которых мне так и не удалось.
Однозначно угадывается автор поста.
Надо было тогда переводить полностью:
goto облом;
Из goto облом; выйдет отличный новый мем :-)
Я на минуту где-то завис, пытаясь понять, что это еще за облом :)
UFO just landed and posted this here
Вот поэтому напрягает стремление к излишне «лаконичным» синтаксисам в новомодных ЯП (всяких Ruby, Scala и т.п.). Хотя некоторые отличились в этом плане и раньше (тот же TCL в котором и условие и «тело» берутся в одинаковые фигурные скобки, например).
А какое отношение новомодные ЯП имеют к 40летнему Си? Проблема-то именно в его синтаксисе.
На мой субъективный взгля там кол-во подобных «неувязок» синтаксических гораздо больше, ибо от всяких скобок и разделителей стараются максимально отказаться. Мне это стремление кажется ошибочным, ибо скобки и разделители помогают читать и бегло взглянув в общем понимать логику кода.
Надо просто правильно форматировать код и не страдать копипастой. Куда более вероятно, что человек дважды нажал ctrl+v, чем дважды напечатал goto fail;. При использовании автоформатирования такая проблема сразу себя проявляет визуально.
И как можно страдать копипастой при чтении?
Я вам пример хуже приведу
if(что-то);
   Действие
Отчасти поэтому лично я предпочитаю форматирование вида:

if (condition) operator;


здесь сразу все ясно и ошибиться практически невозможно.
Как будто вы никогда не писали код в 3 часа ночи.
Production код стараюсь не писать в такое время =)
Поддержу. Расстояние Левенштейна для синтаксически верных конструкций в лаконичных языках невелико. Опечатка в «старомодном» языке скорее всего приведет к ошибке компиляции/интерпретации, а в излишне лаконичном — к неверному поведению. Но свои плюсы у компактных языков тоже, конечно, есть.
Для меня визуально + и — различаются больше, чем plus и minus. Возможно, тут расстояние Левенштейна не работает.
Не «не работает», а следует дополнить особенносятями визуального восприятия, по-хорошему, ещё и учитывать расположение клавиш для популярных раскладок.

CoffeeScript:
([0..5]) # [0;5]
([0...5]) # [0;4]

a b c d  # a(b(c(d)));
a b, c d # a(b, c(d));
a b; c d # a(b); c(d);

if 1
  if 0
    a()
  else 
    b()
c() # b(); c();

if 1
  if 0
    a()
else 
    b()
c() # c();

Изменение всего 1 символа приводит к совсем другому синтаксически корректному коду. На мой взгляд очевидно, что возможен более «помехоустойчивый» синтаксис.
Мне кажется, излишняя лаконичность — это когда часть логики вешают на whitespace (пробелы и табы). Получается, что визуально пустое место (которое легко пропускается глазами) имеет такое же значение, как и сам код.
Если бы отступы были незаметны их бы люди не делали. Из делают именно потому, что они заметны даже в тех языках, где они ничего не значат
Я думаю тут причина в отсутствии лаконичности. Вместо исключений или Maybe monad надо тупо повторять if(x) goto fail после каждой операции. Интересно, они не вычищают dead code и не пользуются статической верификацией хоть какой-то?
Хорошо, давайте вместо goto fail всюду писать throw exeption(). Что-то изменилось?)
Вот Maybe monad — вещь более интересная. Но чтобы не пришлось всюду писать одно и то же — тут так же надо постараться.
А конкретно в данном случае было бы достаточно операции &&.
Для того, чтобы переправить эксепшн наверх не надо писать throw exception — достаточно ничего не писать
А что не так с условиями в Tcl?
«условие и «тело» берутся в одинаковые фигурные скобки»
Т.е. вместо if(условие) { тело } пишешь if { условие } { тело }
Визуально сложнее отличить условие от тела, особенно когда много вложенных if-ов и прочих фигурных скобок.
Неправда, если Вы так говорите, значит, Вы мало писали на тикле.
Какая разница сколько писал когда речь о визуальном восприятии.
Нормальная строчка TCL кода:
foreach el $b {if {[info exists arr($el)]} {lappend res $el}}

При первом взгяде не ясно где тело цикла — точнее почему их как-бы два.

А вот так:
foreach el $b { if(info exists are($el)) {lappend res $el}}

лично мне читается гораздо легче.
Во-первых, Tcl, а не TCL.
Во-вторых, отступы и переводы строк — раз уж Вы радеете за визуальное восприятие.
В-третьих, нет, фигурные скобки здесь полностью оправданы и визуальному восприятию не мешают.
Ох и придирчивы на Хабре сегодня.

> Tcl, а не TCL
en.wikipedia.org/wiki/Tcl
Tcl (originally from Tool Command Language, but conventionally spelled «Tcl» rather than «TCL»; pronounced as «tickle» or «tee-see-ell»[3])

Так что, как видите, TCL более правильное написание — раз уж для вас это важно.

> фигурные скобки здесь полностью оправданы
И чем же они лучше чем круглые скобки в данном случае? В всех языках C-подобного синтаксиса используются круглые скобки, и все довольны.
Нет, TCL не более правильное. Официальное (и правильное) написание — Tcl.

А Tcl — не C-подобный.
> Нет, TCL не более правильное. Официальное (и правильное) написание — Tcl.
Написано же черным по белому — оригинальное название Tool Command Language, используются оба способа написания (TCL и Tcl) и произношения («tee-cee-el» и «tickle») равноценно.
С чего вдруг «Официальное (и правильное) написание — Tcl»? Где написано что TCL — неправильно? Не выдумывайте ерунды.
Ну сходите наконец на tcl.tk
Tool Command Language, Tcl.
> Tool Command Language
А я о чем?
Повторяю вопрос: где написано что TCL — не правильно?
Вам недостаточно
> conventionally spelled «Tcl»
?

Tcl — больше не аббревиатура, если хотите.
Tcl (а не Xyz, Abc, Nom или другие три буквы) — да, потому что это первые буквы в «Tool Command Language». Так совпало ;)
Вы, Sauron, процитировали "conventionally spelled «Tcl» rather than «TCL»", что в переводе означает: "принято записывать «Tcl», а не «TCL»".

Можно ли считать в данном случае, что «не правильно» записывать так, как не принято?

Если да, то вот и ответ на Ваш вопрос.

Если нет, то это скорее Вы «придирчивы на Хабре сегодня».
> Можно ли считать в данном случае, что «не правильно» записывать так, как не принято?
Нет.

> Если нет, то это скорее Вы «придирчивы на Хабре сегодня».
Почему-же? Мне все равно TCL или Tcl, я совершенно не понимаю почему от сути разговора собеседник вдруг перешел на вопросы «правильности» написания TCL. Я к такой ненужной подробности не придирался.
К сведению, фигурные скобки можно и опустить, правда, смысл будет несколько иной.
А зачем тут смотреть на скобки? Вот у вас идет if и за ним два expression-а. По-моему, все очевидно.

Я не пишу ни на тикле, ни на лиспе, если что.
Нет, разница есть: первый параметр if — выражение на языке expr, а второй и опциональный третий — команды тикля. Так что нельзя сказать, что два выражения. Потому, кстати, и квадратные скобки нужны.
Да, согласен, глупость написал. Но общая идея, надеюсь, осталась ясна.
Неправда, если Вы так говорите, значит, Вы мало писали на тикле.

Для непредвзятой оценки как раз и нужен свежий взгляд. Привыкнуть можно к чему угодно.
В тикле для фигурных скобок есть причина, причём довольно серьёзная, точно так же, как в C есть причина для круглых скобок. В C в скобки круглые заключаются выражения, а в фигурные — блоки кода. В тикле нету выражений и блоков кода как таковых, есть текст, который интерпретируется в зависимости от контекста, причём решает это вызываемый код, а не вызывающий (что довольно логично). Скобки в первом параметре команды if означают лишь то, что в теле этого параметра не надо выполнять подстановки в процессе вызова этой команды. Если подстановки выполнять не нужно, то фигурные скобки не нужны.
Скобки в первом параметре команды if означают лишь то, что в теле этого параметра не надо выполнять подстановки в процессе вызова этой команды. Если подстановки выполнять не нужно, то фигурные скобки не нужны.
Вы сломали мой парсер логических выражений.
Вроде логично: если подстановки могут быть, их надо выключить. Если их быть не может — можно не выключать.
У вас было написано две импликации в разные стороны:
1. Если есть скобки, то подстановки выполнять не нужно [интерпретатору, видимо].
2. Если подстановки выполнять не нужно [разработчику, так понимаю], то скобки не нужны.

Это, в общем, и путает. Можно было просто написать, что при отсутствии фигурных скобок (например, в квадратных) интерпретатор выполняет код, при наличии фигурных — не выполняет и передает в макрос как есть.
По сути вопроса я спорить не буду, ибо в Tcl некомпетентен. Просто замечу, что выходит хотели как лучше, сделали логично и унифицированно, а неподготовленному человеку в итоге нечитабельно и неудобно. Чтобы такого не было, надо языки писать как хорошее ПО, с фокус-группами, научными исследованиями со снятием метрик читабельности синтаксиса и прочим.

Между делом говоря, для C есть GCC Statement Expressions, позволяющие в выражениях использовать блоки кода.
if (({int x = 2; (4 == x*x);})) {
    // true
}

Не согласен. Вон в PHP чего понагородили — всем хотели угодить же ж!
Вот поэтому я считаю, что тело if всегда стоит оборачивать в фигурные скобки.
К сожалению, на текущей работе принято, что в случае когда тело if состоит из одной строки, фигурные строки ставить не стоит.
А я считаю, что хороший редактор кода во первых сам исправил бы некорректное форматирование, а во-вторых предупредил бы о наличии недостижимого кода.
Ну и если вдруг редактор не помог, то хороший ревьюер оторвал бы за такой код руки автору.

И мне, честно говоря, кажется, что это несколько более рабочие механизмы, чем обязательность скобочек у if-а.
Скобки в таком случае обычно вопрос договоренности внутри команды. И настройки IDE и системы сборки после этого.
Когда у меня тело if-а состоит из одной строки, то стараюсь разместить тело в той же строке. А иногда перфекционизм начинает доминировать и я ставлю фигурные скобки даже в таком случае =))
В embedded разработке есть паттерн ожидания флага
while(SOME_HARDWARE_FLAG == 0);

который тот же eclipse переписывает в виде
while(SOME_HARDWARE_FLAG == 0)
    ;

считая, что это поможет уменьшить вероятность ошибки вида
while(SOME_HARDWARE_FLAG == 0);
    some_operator();


Естественно, часть людей считают первый вариант (в одну строку) нормальным паттерном, часть — антипаттерном.
может быть, лучше явно показать пустой цикл?
while(SOME_HARDWARE_FLAG == 0) {}
Не знаком с предметной областью, но очень хочется в такой цикл добавить delay на 1мс или что-то вроде. Так делают, или это ересь? Не приведет к throttling?
Это глупость. delay имеет смысл, когда надо освободить процессор для других потоков. Но зачем он нужен, ежели поток всего один?
Странно, а я думал вот так:
Let's say we have an embedded system which has an average loop time of 1ms, and needs only to check a certain input once per second. It seems a waste to continue looping the program, especially when we don't need to do anything most of the time. In this situation, the program will loop 1000 times before it needs to read the input, and the other 999 loops of the program will just be a countdown to the next read. In this case, it is sorely inefficient to have the processor chugging away at 100% capacity all the time. We will now implement an expanded superloop to build in a delay:


Одно ведь дело, если флаг изменится через 1-2мс, но это же может быть и флаг «юзер нажал на кнопку» и чип дергает цикл и считывает volatile переменную тысячи раз в секунду (или сотни тысяч?). Или таки я ошибаюсь и там есть защита от такого?
Ну, эти рассуждения годятся только в том случае, когда delay действительно уменьшает энергопотребление. Зачастую, сам delay через цикл и реализован…
жесть какая =)
окей, спасибо за консультацию!
Добавлю кругозора ради. Инструкция HLT существовала в процессорах Intel начиная еще с 8086, если не раньше (не помню, была ли эта команда в 8008). Но, тем не менее, эта команда практически не использовалась в программах под DOS (и правда, зачем она была нужна?)

Как результат — мой компьютер спокойно держит 6 виртуальных машин с линуксом (я тогда курсовую по сетям делал) — и тормозит всего на двух виртуалках с ДОСом (я пытался делать курсовую по системному программированию).

Для того, чтобы вызов delay уменьшат энергопотребление, требуются три вещи:
1. в системе команд микроконтроллера должна быть команда останова,
2. у микроконтроллера должен присутствовать встроенный или внешний программируемый таймер,
3. реализация функции delay должна уметь пользоваться первым и вторым пунктами.
> не помню, была ли эта команда в 8008

В 8080 точно была.
Задержка и ожидание события — две большие разницы. Если необходимо среагировать на событие чип может уходить в какой-нибудь режим энергосбережения, отключать тактирование части периферии и т. п. Стоит учитывать, что пробуждение занимает время, включения тактирования — тоже. Чем глубже режим энергосбережения — тем больше время пробуждения и больше его дисперсия, что может быть критично в системах реального времени.
Всё сильно зависит от среды исполнения. Когда это голое железо (т. е. совсем без ОС), то задержка — такой же цикл. В зависимости от величины задержки он может выполнять либо просто заданное число итераций, либо считать ожидать некоего значения на внешнем счетчике. Если у вас шедулер/ОС, то иногда имеет смысл сделать yield (переключить задачу и уснуть), иногда — подождать циклом.
Простите что не совсем по теме, но evasi0n jailbreak по прежнему работает, или эту «дырку» данным обновлением тоже прикрыли?
Этот код не должен был дать закоммитить линтер.
Ещё скажите, что CI нужен
Да уж! Очень интересно как у них это получилось.
Надо же, Goto! Как в детстве 20 лет назад, когда на бейсике писали… Не запретили ещё!
Хотя, вру, конечно. На ассемблере потом ещё приходилось.
Ну а теперь смотрим на суть статьи, к чему привело использование goto. И заодно читаем статью msdn, где паттерн вроде бы ровно тот, но за маленьким вроде бы ничего не значащим отличием — отсутствующими здесь скобками.
Вот так использование двух вроде бы не жестко запрещенных паттернов и привело к косяку.
Реальному, живому косяку, а не лайкам-дизлайкам в обсуждении.

Можно вообще писать в машинных кодах супер-программы. Проблема в том, что программисты не всегда глубоко понимают суть тех или иных рекомендаций. И пропускают детали.
Такую ошибку можно допустить независимо ни от каких goto. Замените, к примеру, все goto fail на throw exception(). Что-то изменилось?
или на do{if()break;}while(0); если уж такая сильная готофобия.
Если бы в этом коде использовались исключения, а не поле с кодом ошибки, то такое копирование строки сделало бы код неработоспособным — он бы всегда выбрасывал исключение.
Точно так же, как и сейчас он всегда переходит на fail…
В том-то и дело, что нет.
В блоке fail идёт лишь очистка ресурсов и возвращается полученный код ошибки. Если ошибок не было, этот код будет 0 — нет ошибки.
Код можно посмотреть здесь
Точно так же лишнее выбрасывание исключения с нулевым кодом ошибки могло бы быть обработано как отсутствие ошибки. Представьте на минутку, что мы переписываем только одну функцию, а не перерабатываем весь код программы и связанных библиотек.
Точно так же лишнее выбрасывание исключения с нулевым кодом ошибки могло бы быть обработано как отсутствие ошибки.

А вот за такое надо пересадку рук делать.
Да, зачем вообще какие-то дураки эксепшены придумали? Какие-то там throw, catch — а тут goto fail, гораздо более надежно!
Давно ли в стандарте C появились exceptions? Киньте ссылку на стандарт, пожалуйста.
В С++ — давно, ссылку на стандарт кидать лень, может поверите наслово?

Не, ну я понимаю, что есть люди, считающие что все кроме С — говно (типа Линуса :)), только не надо позиционировать конструкции, которым более полувека, как что-то современное, ок? Программирование, как и другие инженерные области, развивается, если что.
Какое отношение C++ (где очевидно есть исключения) имеет к коду на C, который обсуждается в топике и содержит презренные goto? Или все операционки срочно надо переписать на плюсах только за то, что там есть exceptions, а C безумно устарел даже в стандарте C11? Может они и в ядре будут хорошо работать? Может сразу на Java, то там модель exceptions мне нравится, да и JMM приятна.

У вас, кстати, libstdc++ хорошо влезает, скажем, в 8к ROM + 512 RAM? Плюсы не являются развитием C, но другим языком. C развивается самостоятельно, выходят новые стандарты, улучшаются компиляторы…

Во избежание таких ошибок в высокоуровневом коде на С вполне можно использовать функции-обертки, занимающиеся выделением и освобождением ресурсов, когда лишнее углубление в стек не критично. В языках с механизмом exceptions часто используют try-catch, когда такие накладные расходы допустимы.
Экспшены не универсальны. Как минимум потому, что стек вызова раскручивают, который нужен только для отладки чаще всего.
А ещё нужно жестко запретить копипаст!
Уж к скольким реальным, живым косякам привёл копипаст — и не сосчитать.
>Вот так использование двух вроде бы не жестко запрещенных паттернов и привело к косяку.

По вашей логике если кто-то допустит баг при использовании паттерна «фабрика» или «синглтон», то нужно запретить фабрики и синглтоны?
Лично я для себя прошел такую цепочку:
1. Goto
2. Нет, Goto ж нельзя, запрещают
3. Goto-то можно, оказывается! Есть даже особые случаи.
4. Нельзя обычным программистам, один из десяти обзательно накосячит. а мне можно — я же постиг и свободен.
5. Мне нельзя
И не потому что накосячил. А потому что не нужно.
Вот, например, официальная документация, error handling in COM:

Без обид, но если для вас COM — образец современной технологии, то, наверное, спорить бесполезно.
Без обид, но COM до сих пор живее всех живых. Технология WinRT (куда уж современнее-то?) — и та основана на COM.
Какое goto на ассемблере? Только jmp/rjmp/b/bx/bl/blx/..., только хардкор.
ну goto по сути и есть jmp, просто метка проще записывается :) так что goto и есть хардкор.
Лексема goto обычно встречается в более высокоуровневых языках. Что она транслируется в какой-то вариант оператора безусловного перехода — тоже очевидно.
Ассемблер бывает разные. На в микроконтроллерах PIC есть два оператора безусловного перехода bra и goto.
С ассемблером от microchip я не знаком. Посыпаю голову пеплом. Не понравились они мне в своё время.

Но, предполагая, что в каком-нибудь ассемблере оно может встретиться написал «goto обычно встречается».
Естественно, имелось в виду jmp, jne, jle и т.п.
Кстати, анализатор PVS-Studio вполне себе замечает аномалию в этом коде и сообщает:

V640: The code's operational logic does not correspond with its formatting. The statement is indented to the right, but it is always executed. It is possible that curly brackets are missing. Level: 2

А вообще надо будет правило и касательно именно двух goto сделать.
А на недостижимый код после goto он не жалуется? В Java, например, здесь была бы ошибка компиляции «unreachable code».
Смысла большого нет. Мы стараемся не дублировать предупреждения компилятора, если не можем сделать диагностику чем-то лучше. Поясню на примере. В Visual C++ есть предупреждение, что в классе деструктор объявлен не виртуальным. Диагностика сделана «в лоб». Как результат, пользоваться ей нельзя и она по умолчанию даже выключена. То есть она даёт слишком много бестолковых предупреждений. Ведь далеко не всегда виртуальный деструктор нужен.

У нас сделано умней. Диагностика V599 срабатывает только тогда, когда другие есть виртуальные функции. Это значит, что от класса планируют наследоваться. Следовательно, нужен виртуальный конструктор. Диагностика вполне по делу. И находятся ошибки.

Так вот. Сейчас все нормальные компиляторы предупреждают про недостижимый код. И как они просмотрели это предупреждение — не понятно. Если оно отключено, то тоже не понятно почему.
А тогда зачем правило касательно двух goto? По идее, в этом случае как раз компилятор должен ругаться, как вы и говорите.
Я так просто это написал. В начале, конечно, надо будет изучить вопрос подробнее. Стоит ли делать и как, какая будет польза и т.д.
то есть, проверка на недостижимый код в у вас не делается, так как она есть в компиляторе?
Да. Но есть некоторые разновидности диагностик на эту тему (пример).
gcc имеет такую опцию -Wunreachable-code
Очень хороший пример, что опечатку может сделать кто угодно и где угодно. Можно как мантру повторять, что уж мы то профессионалы не делаем таких ошибок, но…

Устал пытаться донести мысль, что никогда не стоит пренебрегать средствами дополнительного контроля над собой (статический анализ кода и т.п.). Надо такие примеры начать собирать, чтобы было что на «я пишу без глупы ошибок» ответить аргументированно.
Напоминает случай с уязвимостью MacOS, где программист оставил отладочную печать.
story

Видео с курса CS259: Software Debugging от Udacity
Целая минута видео, по-сути без видео, а процесс рисования картинки, вся суть которого передается тремя словами: пароль пишется в лог.
Извиняюсь. Действительно, вырванное из контекста смотрится не очень. В соседнем видео упоминается ещё пара неудачных способов отладки и говорится, что так делать не стоит.
Andreas Zeller знает много интересных историй. К примеру, отладка с помощью плюшевого медведя: прежде чем обратиться к кому-либо за помощью, стоит попытаться сформулировать проблему и рассказать её вслух (плюшевому медведю). Есть большая вероятность, что при формулировке проблема всплывёт перед глазами.
Такого названия не встречал, но по ссылке написано и о медведе. При этом книги вышли в одном году и истории разнятся. Видимо, идея витала в воздухе.
Реквестирую от уважаемых гуру С рефакторинг этой функции, интересно посмотреть как это сделать максимально правильно, спасибо
Просто уберите лишний goto fail; ;)
Всё остальное субъективно и зависит от принятого в вашей компании coding style, ну и от ваших личных предпочтений.
++ Из текста: Чтобы узнать уязвимо ли Ваше Apple устройство/приложение, нужно попытаться загрузить следующий сайт https://www.imperialviolet.org:1266 . Если у Вас это получилось, то у Вас проблема… Вот пример:
image
Всё верно. iOS исправлен в iOS 7.0.6 и iOS 6.1.6. В OS X 10.9.1 все работает. Хорошие новости в том, что, видимо, под удар попала только OS X 10.9, так как у меня на стареньком Mac Air'e (OS X 10.6.8) и Мас Pro (OS X 10.8.4) ни чего не работает.
image
Safari вывела сообщение это.

curl в консоли ответил
curl: (35) error:04091077:rsa routines:INT_RSA_VERIFY:wrong signature length
Там в самом конце исходников:
  if ((err = SSLAllocBuffer(&key, keyDataLen)))
        return err;
	assert(ctx->sslTslCalls != NULL);
    if ((err = ctx->sslTslCalls->generateKeyMaterial(key, ctx)) != 0)
        goto fail;

Вот я думаю, строка assert(ctx->sslTslCalls != NULL); это такая же ошибка, или просто ошибка в редактировании?
К слову, в исходниках всё плохо касательно форматирования кода. В смысле, очень-очень плохо.
И скобки вразнобой (одних только if — три варианта написания), и табы вперемешку с пробелами, где-то операторы отбиты пробелами, где-то нет…
Такое бывает, когда код писало много поколений
А разве простейший статический сканер кода не находит дублирующие строчки? Дубли всегда что то значат же
Сами по себе дубли ещё ничего не значат. Вполне корректный код:

*p++ = 0;
*p++ = 0;

A[i++] = GetNext();
A[i++] = GetNext();

Особенно много такого может быть из-за макросов или автосгенерированного кода.
А так да, инструменты вполне помогают найти такое. См. мой комментарий выше.

код то корректный, но смысл его? Ооочень редко он оправдан
Дублирующиеся строки и лишние табуляции/пробелы то и дело появляются при работе автоматического merge, даже в git'е. Как вариант, неправильное исправление конфликта (которые тоже не всегда показываются правильно). Само по себе это не проблема, сама проблема в том, что diff'ы после таких операций нужно просматривать всегда.
Во первых, пользуйте фигурные скобки
Во вторых, автоматический реформат кода на коммите должен быть, чтобы репозитории всегда лежал правильно отформатированный код
В третих, при компиляции такого, должна быть ошибка про unreachable code
В четвертых, goto — зло
Sign up to leave a comment.

Articles