vak: (Default)
[personal profile] vak
Сложить два целых числа, вернуть целое. Породить исключение в случае арифметического переполнения.
int add(int a, int b);
Удивительно, сколько народу обламывается на этой задачке.

Date: 2020-08-02 23:10 (UTC)
archaicos: Шарж (Default)
From: [personal profile] archaicos
Вы не поняли сути. Компилятор не выискивает UB, и найдя, решает покуражиться просто заради прикола.

Нет. Компилятор смотрит на вещи так, как-будто UB не происходит. Т.е., например, он видит выражение "a + 1 > a" как 1, если a - signed int. И если такое выражение влияет на логику оптимизатора (потому, например, что оно является условием if или тернарного условия), то какой-то код может быть и выкинут. Но могут быть и более тонкие последствия. Например, из-за того, что то выражение равно 1, компилятор может счесть, что диапазон значений какого-то другого выражения (или переменной) может быть ограничен интересным образом, что в свою очередь может иные оптимизации разрешить.

Date: 2020-08-03 08:08 (UTC)
waqur: (Default)
From: [personal profile] waqur
Как-то была история с LLVM, касающаяся бесконечных циклов с пустым телом. С точки зрения стандарта C++, такие циклы — это UB, так что llvm их просто выбрасывал. Когда разработчики Rust наткнулись на это — была та ещё драма. Вопрос решался пустой ассемблерной вставкой с volatile-аттрибутом, IIRC.

Date: 2020-08-03 15:50 (UTC)
archaicos: Шарж (Default)
From: [personal profile] archaicos
Опять же, не «UB, а значит можно выкинуть», а у кода пустого бесконечного цикла нет никаких т.н. side effects (доступа к volatile-переменным, модификации объекта или файла, вызова функции, которая может сделать одно или более из перечисленного, и т.д. – по стандарту), и значит, что цикл можно выкинуть.
В стандарт просто не внесли зависание как побочный эффект (вероятно, забыли, хотя зуб не даю, т.к. очевидно, бесконечные циклы в ходу издревле). Ну и вот, бесконечный цикл пал жертвой оптимизации в какой-то момент.