Комментарии 17

"не надо так"… Я прямо даже и не знаю, как сказать.


А в сях есть способ написать


dword r = a — b;
if (was_overflow) r=0;


чтоб скомпилировалось в проверку флага после вычитания?

Как в Rust'е, да? Типа checked_sub. Если я не ошибаюсь, то нет. Вычитание неотрицательных DWORD чисел само по себе уже опасно. Как мы можем сравнивать результат с нолём в отрицательную сторону?

Я не знаю, как другие бы сделали это лаконично, я бы сперва числа сравнил друг с другом перед вычитанием. Ради интереса, я сейчас изучаю Rust, и стал на эти проблемы чаще обращать своё внимание.
В стандартных пока что нет (работы по добавлению ведутся), но в GCC и clang давно уже да.
Спасибо.

Интересно, а

dword r = a-b;
if (b > a) return 0; else return r;

соптимизируется на ASM уровне само или нет?
Несложно проверить через Compiler Explorer.

GCC (O2):
mov eax, edi
mov edx, 0
sub eax, esi
cmp edi, esi
cmovb eax, edx
ret

Clang (O2):
xor eax, eax
sub edi, esi
cmovae/cmovge eax, edi (ae for uint32_t, ge for int32_t)
ret

Остальные компиляторы можете попробовать по аналогии там же.
да, уже подёргал там в разных вариациях.
ни один из них не свернулся в sub + jo/jno…

При этом вариант с __builtin_sub_overflow сворачивается хорошо
godbolt.org/z/sq63d3
Зато на ARM получается отлично:
subs w8, w0, w1 # вычесть из w0 (a) w1 (b), положить результат в w8 (a-b)
csel w0, wzr, w8, lo # сравнить содержимое wzr (ноль) с w8 (a-b), если строго меньше, то положить в w0 (возвращаемое из функции значение) wzr (ноль), иначе w8 (a-b)
ret
В каком варианте сырка?
Что-то GCC/arm с -O3 мне даже вариант с builtin выдаёт что-то странное.
Кстати, а чем не устроил вариант выше с cmov? Он быстрее, чем sub/jo, потому что в нем вообще переходов нет (и потому нельзя их неверно предсказать).
Проблема не в cmov/jo а в двух — sub + cmp, когда sub это уже cmp по сути.
то есть да, clang делает хорошо :)

я ступил и смотрел только разные варинты записи для GCC.

А вот компилятор Rust'а предлагает, и в 99% случаев его предложения правильные. Почему? Потому что компилятор ууууумный. А язык правильный.


Последняя Mother of All Errors, которую я словил, добавив в невинную структуру ещё одно поле состояла из ~10 строчек, в которых мне объяснялось, что из-за этого поля (совсем в другом месте, совсем другую структуру) нельзя больше безопасно передавать между тредами. Причём в ошибке мне даже сказали, что можно ещё в одном месте заменить Fn на FnOnce, и тогда будет хорошо. Я сделал — и стало хорошо.

Ну, справедливости ради, многое из того, что проверяет PVS-studio и при этом не завязано на язык (вроде одинаковых веток в условном операторе), сейчас не ловят ни компилятор, ни Clippy, так что есть куда расти.

Рассмотрим ошибку, которую я разбирал в статье

Ошибка лютая, конечно.
Прикольно, но бессмысленно ;). Анализатор убрал код, который с точки зрения языка C++ является лишним.

А если как-то так поставить вопрос, чтобы это служило индикатором некооректной логики?
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Информация

Дата основания
2008
Местоположение
Россия
Сайт
www.viva64.com
Численность
31–50 человек
Дата регистрации

Блог на Хабре