LINUX.ORG.RU

А как в вашем ЯП относятся к целочисленному переполнению?


0

4

Навеяло недавним забавным багом в Диабло. Вот взять джаву. Вроде современный безопасный язык, память не расстрелять, хоть ты что делай, нулл не разыменовать, все такие баги вылетают с исключениями. Вот с делением на 0 не помню, но вроде тоже исключение вылетит, если не float делишь. А int переполнится и фиг ты об этом узнаешь.

Я встречал очень мало случаев, когда переполнение int-а при арифметической операции было бы корректным выполнением алгоритма. В реальной жизни об этом не думают вообще никогда, ибо 4 млрд это много и хватит каждой домохозяйке. Раз в сто лет не хватает и там вылезает бага. И бага, обычно, пренеприятная. Например как в диабле.

Чисто мое имхо — процессор должен кидать исключение (вызывать прерывание или как там такие ситуации обрабатываются) при переполнении по умолчанию, которое рантайм языка уже может обрабатывать как ему надо. В 99% случаев. А для 1% использовать другие инструкции, не кидающие исключение, ставить какой-нибудь флаг или использовать другой вариант. Ну это на аппаратном уровне, без этой поддержки реализовать отлов переполнения сложно, не будешь же после каждого сложения ставить проверку cf.

А как ваш ЯП помогает программисту в ситуации, когда происходит непредвиденное переполнение? Есть варианты всяких пайтонов, в которых прозрачно промоутится до многобайтной арифметики, но это, по-моему, жутко неэффективно (кстати аппаратное исключение и таким языкам поможет ускориться).

Или я не знаю возможностей современных аппаратных платформ и это всё есть, просто глупые джавы это не используют?

★★★★★

В реальной жизни об этом не думают вообще никогда

Если вот лично ты об этом не думаешь, то это не означает что об этом не думает никто и никогда.

provaton ★★★★★
()
Ответ на: комментарий от provaton

Я лично об этом стараюсь думать. Но я вижу чужой код, я виду факапы разработчиков, которым, скорее всего, платят раз в 10 больше, чем мне.

Вообще комментарий странный. Про управление памятью сишники тоже стараются думать. Огромного числа багов, связанных с кривым менеджементом памяти, это не отменяет. Тут скорее такие ошибки раньше выстреливают.

Legioner ★★★★★
() автор топика

без этой поддержки реализовать отлов переполнения сложно

В adа слышал имеется, можно поискать как там реализовали. Чтобы выяснить действительно сложно, или не столько нужно.

anonymous
()

Уже не помню, но кажется, что Ада бросает исключение, но тут надо одного странного типа спрашивать ( см. токсы).

dave ★★★★★
()

Seacord, «Secure Coding in C and C++», глава 5, gcc -ftrapv, FPE_INTOVF_TRAP.

auto12884839
()

Я встречал очень мало случаев, когда переполнение int-а при арифметической операции было бы корректным выполнением алгоритма.

В моей недо-ос для avr переполнение int — это штатная ситуация.

Чисто мое имхо — процессор должен кидать исключение.

Это бы мне очень сильно мешало.

Lang: ANSI-C

beastie ★★★★★
()
Ответ на: комментарий от dave

Ага, вот как оно небось работает в sbcl! Что-то хочу нагуглить какие теги каким объектам присваиваются, да не гуглится. А раньше я видел эту табличку.

onanij
()

А на аппаратном уровне нет разницы между signed и unsigned. Просто флаг SF выставляется на случай, если это имелось ввиду signed, а CF на случай unsigned. Потенциальных оверфло на всем диапазоне выходит аж 4 штуки. Чо теперь на каждый чих исключение кидать? Такие вещи софтово проверять нужно. Берешь нормальный язык с бигнумом и не выдумываешь :)

Может чо напутал, просто асмом по молодости увлекался, так-то не спец.

anonymous
()
Ответ на: комментарий от Legioner

Лишние cycles. Исключение обрабатывать/игнорить надо. Но да, наверно не так бы уж сильно и мешало. Но оно всё равно лишнее.

beastie ★★★★★
()
Ответ на: комментарий от anonymous

А на аппаратном уровне нет разницы между signed и unsigned. Просто флаг SF выставляется на случай, если это имелось ввиду signed, а CF на случай unsigned. Потенциальных оверфло на всем диапазоне выходит аж 4 штуки. Чо теперь на каждый чих исключение кидать?

Хорошее замечание. На каждый чих не вариант, надо или делать две версии команды сложения, вычитания для signed/unsigned, или переключение режима процессора.

Такие вещи софтово проверять нужно.

Очень медленно.

Legioner ★★★★★
() автор топика
Ответ на: комментарий от Legioner

А стрельнувший хардварный трап думаешь быстрый процесс? Лучше в предиктор иногда промахиваться, чем такие трапы ловить.

anonymous
()
Ответ на: комментарий от dave

Про sbcl

Хотя я всё равно не пойму, если, конечно, мы про одно и то же.

В sbcl есть некий тег в нижних битах объекта/указателя. У fixnum это 000, поэтому некоторые операции не меняют этот тег и их можно делать в одну/пару инструкций, если тип известен заранее.

Но если сделать (1+ most-positive-fixnum), то число должно сброситься в 0, не? Так как тогда происходит переключение на bignum?

onanij
()
Ответ на: комментарий от anonymous

Ну и да, аппаратное исключение вместо софтовой проверки замедляет, а не ускоряет ее.

Не замедляет, а значительно ускоряет. Переполнение это исключительная ситуация, которая встречается 1 раз на миллиард операций. Аппаратная обработка в ситуации, когда переполнения нет, занимает один такт процессора. Софтовая проверка переполнения занимает кучу тактов процессора всегда и при обычной реализации порождает ветвление, ухудшая работу предсказателя кода.

Если программист ожидает, что в данном месте будет переполнение, он использует особым образом обозначенную операцию (или тип данных), компилятор генерирует инструкцию, не проверяющую переполнение, это, естественно, подразумевалось.

Legioner ★★★★★
() автор топика

А в clisp, наверное, на всём диапазоне целых чисел bignum. Хотя не знаю, не проверял. Кто выскажется на эту тему - буду благодарен.

onanij
()
Ответ на: комментарий от anonymous

А стрельнувший хардварный трап думаешь быстрый процесс?

Плевать, если он стрельнул, это то же самое, что деление на ноль или разыменование нулевого указателя. Кто-нибудь, может, и обработает, а почти все тупо упадут в корку и правильно сделают. Если человек строит логику программы на невалидных операциях и отлавливая сигналы эту логику меняет, ему надо в дурку.

Legioner ★★★★★
() автор топика
Ответ на: комментарий от Legioner

Переполнение чего, торагой? Вот у тебя число в rax/eax/подставь по вкусу. И чьё переполнение ты будешь ловить аппаратно: регистра или типа языка?

Причём, как сказали, в случае с signed их будет несколько.

onanij
()
Ответ на: комментарий от onanij

Переполнение это выставление бита cf при сложении/вычитании unsigned. Или sf при signed.

Естественно я про типы, «нативно» поддерживающиеся процессором, 8/16/32(/64), если мы про x86(_64). Обычно они однозначно мапятся на типы во многих ЯП.

Legioner ★★★★★
() автор топика
Ответ на: комментарий от Legioner

Если человек строит логику программы на невалидных операциях и отлавливая сигналы эту логику меняет, ему надо в дурку.

Зачем ud2 или int3 в отладчиках, ловля segfault'ов в сборщиках мусора, итд? По-моему, ты не прав

onanij
()
Ответ на: комментарий от Legioner

Если человек строит логику программы на невалидных операциях […], ему надо в дурку.

Ну вот. ☹ Мне оказывается в дурку надо.

beastie ★★★★★
()
Ответ на: комментарий от Legioner

Тады может и хорошая идея. С тебя тестовый процессор ;)

onanij
()

В нашем языке программирования это undefined behavior для знаковых целых - компилятор всегда прав, программист всегда виноват :)

annulen ★★★★★
()
Ответ на: комментарий от tailgunner

Спасибо, интересно, про что-то такое я и спрашивал.

Legioner ★★★★★
() автор топика
Ответ на: комментарий от onanij

Инструкция - это неправильно. Надо маску прерываний

Инструкция есть уже сейчас. Насчет маски - я не берусь судить, что это обязательно правильнее.

tailgunner ★★★★★
()
Ответ на: комментарий от beastie

Ну я утрирую, могу представить себе, например, что тот же пайтон при сложении 4-хбайтовых чисел просто складывает их ничего не проверяя, а при получении прерывания делает promote их внутреннего представления до длинной арифметики. Наверняка это ускорит выполнение большинства программ.

Но это явно не тот код, который пишет большинство.

Legioner ★★★★★
() автор топика
Ответ на: комментарий от onanij

Что вы! И в мыслях не было. Просто хотел высказать мысль, что целочисленное переполнение порой очень удобным инструментом может быть.

beastie ★★★★★
()
Ответ на: комментарий от onanij

Теоретически — да. Практически — мега8 заброшена. С неё я начинал, но 328 и в два раза жирнее и в два раза дешевле.

beastie ★★★★★
()
Ответ на: комментарий от Legioner

Переполнение это выставление бита cf при сложении/вычитании unsigned. Или sf при signed.

тогда сложение больших чисел будет жутко тормозить, если на каждое выставление флага переноса будет дёргаться исключение

Harald ★★★★★
()

Python, мы к целочисленным переполнениям не относимся.

PolarFox ★★★★★
()

А java — язык никаким образом не современный.

PolarFox ★★★★★
()
Ответ на: комментарий от Legioner

Если человек строит логику программы на невалидных операциях и отлавливая сигналы эту логику меняет, ему надо в дурку.

Гыы.. http://bolknote.ru/2013/02/23/~3881#02

Вспомнилась еще защита проги под оффтопик, полностью реализованная исключениями (и вплетенная в функционал проги, ага). Говорят, ломать ее было «одно удовольствие»

Kuzz ★★★
()
Ответ на: комментарий от Legioner

Такие вещи софтово проверять нужно.

Очень медленно.

Да ладно, один jump carry какой-нибудь в суперскалярной архитектуре погоды не сделает.

nanoolinux ★★★★
()
Ответ на: Про sbcl от onanij

В sbcl есть некий тег в нижних битах объекта/указателя. У fixnum это 000.

Можно я вмешаюсь? Спасибо. Меня всегда интересовало: почему теги суют в младшие биты, а не старшие?

  • Младшие биты:
    • подготовка фикснамов: «sar 3» / «sal 3»
    • выделение тега: «and 0x7»
    • каст к указателю: «and 0xFFFFFFF8»
  • Старшие биты:
    • подготовка фикснамов: нулевая стоимость, если выделить два тега под положительные/отрицательные числа
    • выделение тега: «shr 28»
    • каст к указателю: «shl 3»

Налицо превосходство старших битов же!

ilammy ★★★
()
Ответ на: комментарий от ilammy

Наверное указатели всегда выровнены по 8 байтам, поэтому ничего не теряешь. А shl 3 потеряешь 7/8 адресного пространства.

Legioner ★★★★★
() автор топика
Ответ на: комментарий от Legioner

Ничего не теряется в обоих случаях. У указателей же в любом случае три незначащих бита из-за выравнивания. При теге в младших битах указатель не трогается, но эти биты заняты тегом. В случае старших битов указатель просто сдвинут вправо на эти три бита. Чистить тег перед использованием указателя с тегом как нормального указателя ведь надо? Я не знаю, может не надо и именно в этом плюс. И в том, что проверка «фикснам/объект» быстрее.

ilammy ★★★
()

Навеяло недавним забавным багом в Диабло.

Дальше про жабу не читал.

bhfq ★★★★★
()
Ответ на: комментарий от tailgunner

Однажды Intel & AMD решат, что нынешние архитекруты себя изжили и начнут выпускать оптимизированные Lisp машины. Вот тогда посмеемся. А лучше не интел с амд, а какой-нибудь очередной Торвальдс всех их закопает. Я лично не понимаю почему они умерли, единственное мое объяснение - неосиляторство лиспа 99-мя процентами php-обезьянок (читай нынешних «программистов»).

unt1tled ★★★★
()
Последнее исправление: unt1tled (всего исправлений: 1)
Ответ на: комментарий от unt1tled

Но ведь причина их смерти совершенно очевидна.

Расскажешь?

Конечно. Lisp машины умерли, потомцу что были нафиг не нужны^W^W^W^W универсальные машины с универсальными ОС порвали их по критерию стоимость/эффективность.

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.