- 1
- 2
if(!true) // это - не говнокод. это - заглушка.
return false;
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+142
if(!true) // это - не говнокод. это - заглушка.
return false;
Оправдывается ещё )
3.14159265 21.02.2013 17:05 # +2
Напомнило: http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html
pitch 21.02.2013 17:16 # 0
Govnocoder#0xFF 21.02.2013 20:41 # +16
bormand 21.02.2013 21:26 # +2
Спасибо за ссылку. Красивая фраза там в конце третьей части - C migrated from being a "low level systems programming language that was a tiny layer above PDP assembly" to being a "low level systems programming language, trying to provide decent performance by breaking many people's expectations.
guest 26.02.2013 01:42 # 0
bormand 26.02.2013 05:34 # +4
Слабо написать парсер довольно примитивного синтаксиса? ;)
А грабли то, в основном, не синтаксические, а логические. Ради того, чтобы компилятору и его разработчику было свободнее, в стандарте рассована куча UB'ов и ID'ов. А почти любой UB - потенциальный разрыв шаблона для того, кто сталкивается с ним в первый раз, ну разве что кроме самых очевидных, до которых можно самому догадаться. Да и даже во вполне определенных областях есть грабли - например если int a = -5 и unsigned b = 10, то что вернет a<b? А чему равна 1/2? А еще до с++11 не было никакого понятия о тредах, все это отдавалось на откуп реализации, со всеми вытекающими последствиями...
Пример - разадресация NULL'а. В жабошарпике это определенное поведение - вброс экцепшена. В сишке же все думают, что должен быть краш\сегфолт и т.п. Но на самом деле это UB, и может случиться все что угодно, от нормального продолжения работы до краша.
carsten 28.02.2013 18:33 # 0
Сравнил мягкое место с пальцем. Синтаксис сложен для парсера, но для человека он не так сложен. Это как человеку раз плянуть распознать на картинке пару объектов, но алгоритмически над этим ломают годы уже десятилетия, как же тупой компьютер научить распознавать объекты без предварительного брутфорса и огромного количества ошибок.
>сравнение int и unsigned int
>В сишке же все думают, что должен быть краш\сегфолт и т.п. Но на самом деле это UB
По-моему, это довольно очевидные вещи из разряда "здравый смысл". Алсо, это всё corner cases, с которыми вполне можно жить.
bormand 28.02.2013 19:39 # +2
Относительно большинства многих других языков с++ как раз таки сложен. Как синтаксисом так и семантикой. Что-то даже не приходит на вскидку пример языка, который бы оказался сложнее с++ по этим характеристикам. Поможете?
> По-моему, это довольно очевидные вещи из разряда "здравый смысл".
Ну дык. Если иметь 2-3 года опыта в c/с++, когда-либо сталкиваться с похожей проблемой или где-то о ней прочесть, и смотреть на эту проблему на маленьком куске кода - то все очевидно...
Вот реальный случай из проекта моего друга: проект компилируется без ошибок и предупреждений, но вылетает посреди работы. valgrind показывает доступ за границы выделенной памяти в конструкторе некого класса. Догадаетесь ли вы с первого раза, что в проект закралась лишняя ашка, в которой описана обрезанная версия класса, видя которую new выделяет намного меньше памяти чем надо?
Если в программе нарушено правило aliasing'а указателей, здравый смысл чем-то сможет помочь? Или все-таки придется почитать о нём?
С++ очень мощный язык, и мне нравится как сам язык, так и его возможности. Но я считаю, что в то же время этот язык сложный, и мест для прострела ноги в нем вполне хватит каждому. И здесь очень много вещей, которые надо знать, т.к. догадываться придется долго, или они будут работать на одном компиляторе, но внезапно будут вести себя по-другому на другой архитектуре\компиляторе\опциях.
LispGovno 28.02.2013 21:12 # 0
Автоматическое распараллеливание не сработает? Ну не всегда это нужно, а догадаться можно.
bormand 28.02.2013 22:14 # +1
Холодно, здравый смысл не всегда помогает с сишкой ;)
Там все гораздо веселее, вот, почитай: http://dbp-consulting.com/StrictAliasing.pdf
LispGovno 01.03.2013 07:06 # 0
LispGovno 01.03.2013 07:27 # 0
А если я записываю в область памяти и там переменных нет, но указатели-аласы имеют указатели разных типов и не принадлежат к спску правил, то я опять же получу UB?
bormand 01.03.2013 08:16 # +1
LispGovno 01.03.2013 08:27 # 0
bormand 01.03.2013 08:31 # 0
Эм, а разве они по стандарту не одинакового размера, к тому же равного размеру указателя?
LispGovno 01.03.2013 07:56 # 0
Боль! Вообщем они снова придумали с каждым разом все более ожидаемую хуйню.
Правильно ли я понял, пользоваться union ом для разруливания в С++ нельзя (только в си), так как он не дает гарантий по стандарту? Приходится копировать память, чтобы это разрулить туда и обратно? Хорошая оптимизация.
LispGovno 01.03.2013 08:20 # 0
По стандарту С++24 компилятор крестов обязан приставлять к яйцам Colt Python .357 Magnum. Он должен делать это на растоянии не больше чем 0.11 метра до цели и не ближе 0.90, чтобы жертва не почувствовала и не пришла в смятение раньше времени. Следует также маскировать его под синие розы. При каждом использовании UB, нажимать на спусковой крючок с задержкой не более implementation defined. Если же жертва сама случайно нажмет на спусковой крючок - это UB (но мы то с вами знаем что будет).
bormand 01.03.2013 08:25 # +1
А с memcpy компиляторы неплохо расправляются, к примеру gcc вот это: Превращает вот в это:
LispGovno 01.03.2013 08:29 # +1
bormand 01.03.2013 08:39 # +1
Это да. А компиляторы с/с++, особенно gcc, идут путем замены предсказуемости в одних ситуациях на скорость в других...
Забавно, но чем извращенней байтоебство, чем больше оно давало профита раньше, тем хуже оно работает с нынешними оптимизаторами.
LispGovno 28.02.2013 21:16 # 0
a проапгрейдится до unsigned и станет например 0хFFFFFFFB и a<b вернет false
>А чему равна 1/2?
Очевидно 0.
bormand 28.02.2013 22:19 # +1
А теперь задумайся ненадолго - это здравый смысл, или знания, полученные за годы работы с сишкой? Через сколько месяцев или лет после первого знакомства с сишкой ты узнал это правило про операции с unsigned и signed одинакового размера?
> Очевидно 0.
Ну да, этот пример действительно слишком простой. Тут после пары тестов можно догадаться что происходит.
LispGovno 01.03.2013 06:51 # +1
Когда достиг почтенного возраста. Уверен, что есть ещё очень много неизведанных граний. Нужно как-то взять стандарт и прочитать его наконец. Правда жить после этого станет не интересно, так как буду знать все тайны мироздания.
TarasB 01.03.2013 10:11 # 0
Будет предупреждение и я сам приведу обе части к знаковому или беззнаковому типу так, как мне надо.
Lure Of Chaos 22.02.2013 02:11 # +1
govnomonad 22.02.2013 05:42 # +4
santa_microbe 22.02.2013 06:35 # +5
govnomonad 22.02.2013 08:37 # 0
HaskellGovno 22.02.2013 08:42 # +5
roman-kashitsyn 22.02.2013 09:56 # +4
tir 22.02.2013 12:02 # 0
П. С. Не вижу ничего плохого в такой практике. Возможно забыли подчистить. Сам так иногда делаю.
pitch 22.02.2013 12:56 # 0
tir 22.02.2013 13:01 # 0
scriptin 22.02.2013 18:58 # +2
HaskellGovno 22.02.2013 23:36 # 0
absolut 23.02.2013 09:54 # +1
bormand 23.02.2013 10:05 # +3
absolut 23.02.2013 10:19 # +1
3.14159265 25.02.2013 16:04 # +1
guest 26.02.2013 01:44 # 0
плохо сделано, я думал намного лучше будет.
bormand 26.02.2013 06:02 # 0
Если функцию поправят, и она внезапно перестанет вбрасывать исключение - весь код, который ее юзал получит утечку управления, что намного серьезнее описанной вами проблемы.
Решением была бы, наверное, аннотация [NoReturn] или новый флажок в бинарном формате, выставляемый как в классе, где она описана, так и в классах, которые ее используют(!). И строгая проверка всего этого: если в классе А была функция, не возвращающая значения, а класс B ее юзал, то если класс B не пересобирали, а в классе А она иногда стала возвращать управление - должна быть выдана ошибка.
И, видимо, никому не надо такой геморрой ради таких редких случаев...
guest 26.02.2013 09:32 # 0
так .net всё равно верифицирует код на стадии jit-компиляции. если вдруг что-то поменяется (что вряд ли вероятно, т.к. такие функции обычно private/internal) то он просто бы выдал ошибку верификации
bormand 26.02.2013 10:38 # +2
При всем при этом компилятор не выдаст ни одного ворнинга. Поэтому, имхо, без аннотации [NoReturn] такие приемы с "гарантированным" вбросом исключения бесполезны и небезопасны. Этот код абсолютно корректен с точки зрения компилятора и верификатора, но doSomething() во втором случае получит управление, хотя писавший test() об этом не подозревал.
LispGovno 26.02.2013 11:08 # +1
bormand 26.02.2013 12:16 # 0
Ну все правильно делает. Здесь noreturn это часть контракта.
P.S. В gcc тоже есть __attribute((noreturn)), но ворнинга про "недоступный код" на этом примере почему-то не выдается.
bormand 26.02.2013 12:17 # +1
carsten 28.02.2013 18:53 # +1
Согласен, что это небезопасно. Но с учётом того, как много разного мусора затащено в .NET (минималистичным его не назовёшь), то появление поддержки такой фичи в рантайме не было бы уж таким "геморроем ради таких редких случаев" (повторяю, BCL кишит такими утилитными функциями).
И, алсо, аннотацию лучше назвать не [NoReturn], а [MustThrow]. Как-то не ортогонально, что все методы могут быть и MustReturn, и нет (то бишь void), но MustThrow отсутствует, хотя это такой же exit point из функции.
guest 05.03.2013 15:58 # +2