Автор Тема: А нужен ли в принципе контроль переполнения int типов  (Прочитано 13057 раз)

trurl

  • Full Member
  • ***
  • Сообщений: 133
    • Просмотр профиля
Вижу еще проблему. Каждый раз, встретив [CHECHRANGE = OFF] при чтении программы, будешь задумываться: а почему? То ли автор уверен, что переполнения не будет, то ли наоборот.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Да, и коль уж заговорили о переполнениях, выскажу старую свою мысль: система типов и у Оберона и у прочих современных ЯП (типа той же java например, да и плюсов и haskell'я) - дырявая. У строго типизированных она почему-то запрещает например преобразование real->int, но при этом разрешает int+int. А ведь и то и другое может привести к одному и тому же - к переполнению/порче значения.

Пусть у нас есть тип Int(N), где N - битность этого целочисленного типа. Тогда, очевидно в случае сложения двух чисел этого типа результат не будет иметь тип Int(N), он будет иметь тип Int(N+1).

Int(N)+Int(M) = Int(Max(N,M)+1)
Int(N)*Int(M) = Int(N+M)

Поправьте если где-то ошибся.

Далее - есть тип представления числа (сколько он там в памяти машины места занимает) и логический тип (какое множество значений по смыслу программы валидно). Это разные штуки, и не надо их смешивать. Если в языке одно от другого отделено, то это позволяет в ряде случаев выполнять рантайм проверку только когда логический вычисленный (по правилам приведенным выше) тип становится больше машинного (производится автоматическое приведение к логическому типу с проверкой).

Либо требовать рукотворного явного приведения типов. Типа a,b,c,d : int_4; a:=int_4(a+b+c+d); Только программировать в таком стиле будет не слишком удобно.
Y = λf.(λx.f (x x)) (λx.f (x x))

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Да, и коль уж заговорили о переполнениях, выскажу старую свою мысль: система типов и у Оберона и у прочих современных ЯП (типа той же java например, да и плюсов и haskell'я) - дырявая. У строго типизированных она почему-то запрещает например преобразование real->int, но при этом разрешает int+int. А ведь и то и другое может привести к одному и тому же - к переполнению/порче значения.
В Хаскелле есть же два вида целых чисел -- фиксированные Int и резиновые Integer.
Integer+Integer может привести к переполнению памяти, если закончится память у компьютера, но упомянутая в теме проблема не возникает.
С Int+Int ситуация немного другая. В Хаскелле считается, что Int -- это по сути перечисление целых чисел, замкнутых по кругу, и если сложить max_int и 1, то получим min_int, а не переполнение. То есть тоже проблемы вроде как нет...
« Последнее редактирование: Декабрь 28, 2012, 11:40:02 am от Geniepro »
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Berserker

  • Sr. Member
  • ****
  • Сообщений: 254
    • Просмотр профиля
То есть никаких проверок + отдельно классы длинных чисел. Ничего нового.

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
в x86 такой флажок тоже есть

Флажок проверять надо, а это медленно. Если б сразу исключение...
Какое такое исключение? На уровне процессора? Спасибоненадо. А чтобы его бросить проверка всё равно нужна. Так что исклчение не медленнее условного перехода по этому флажку, стоящему сразу за арифметической операцией (есть, кажется, такой в системе команд).

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
в x86 такой флажок тоже есть

Флажок проверять надо, а это медленно. Если б сразу исключение...
Какое такое исключение? На уровне процессора? Спасибоненадо. А чтобы его бросить проверка всё равно нужна. Так что исклчение не медленнее условного перехода по этому флажку, стоящему сразу за арифметической операцией (есть, кажется, такой в системе команд).
Иногда процессор умеет при переполнении дергать за прерывание если все правильно сконфигурировано.
Y = λf.(λx.f (x x)) (λx.f (x x))

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Флажок проверять надо, а это медленно. Если б сразу исключение...
Какое такое исключение? На уровне процессора? Спасибоненадо. А чтобы его бросить проверка всё равно нужна. Так что исклчение не медленнее условного перехода по этому флажку, стоящему сразу за арифметической операцией (есть, кажется, такой в системе команд).

А то, что при обращении к нулевому указателю возникает исключение на уровне процессора - тебя не смущает? :) И ты уверен, что тупая проверка каждый раз перед таким обращением будет "не медленнее" (не говоря про объем кода, который в свою очередь влезает/не влезает в кеш)?

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Флажок проверять надо, а это медленно. Если б сразу исключение...
Какое такое исключение? На уровне процессора? Спасибоненадо. А чтобы его бросить проверка всё равно нужна. Так что исклчение не медленнее условного перехода по этому флажку, стоящему сразу за арифметической операцией (есть, кажется, такой в системе команд).

А то, что при обращении к нулевому указателю возникает исключение на уровне процессора - тебя не смущает? :) И ты уверен, что тупая проверка каждый раз перед таким обращением будет "не медленнее" (не говоря про объем кода, который в свою очередь влезает/не влезает в кеш)?
По моему, в данном случае корректней говорить о прерывании нежели о каком-то там исключении на уровне процессора.
Y = λf.(λx.f (x x)) (λx.f (x x))

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
По моему, в данном случае корректней говорить о прерывании нежели о каком-то там исключении на уровне процессора.

Пусть будет прерывание. Главное, что это не ручная проверка, расходующая такты и код.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
По моему, в данном случае корректней говорить о прерывании нежели о каком-то там исключении на уровне процессора.

Пусть будет прерывание. Главное, что это не ручная проверка, расходующая такты и код.
С другой стороны, такое решение все равно будет расходовать например энергию, что в ряде случаев критично. Поэтому целесообразность всегда и везде проверять переполнение все же под сомнением.
Y = λf.(λx.f (x x)) (λx.f (x x))

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
С другой стороны, такое решение все равно будет расходовать например энергию, что в ряде случаев критично. Поэтому целесообразность всегда и везде проверять переполнение все же под сомнением.

Можно, конечно, пойти на компромисс. Вынести поведение при переполнении за рамки языка (undefined behavior) с одной стороны, с другой - предоставить честный способ работать с битами и заспекать поведение при переполнении для соответствующих типов (например сказать, что целочисленные unsigned никогда не "переполняются" и ведут себя вот так). Тогда можно в дебаге иметь все проверки, а в релизе спокойно отключать их (ибо undefined behavior) если железо напрямую не поддерживает.
« Последнее редактирование: Декабрь 28, 2012, 03:35:39 pm от vlad »

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Вынести поведение при переполнении за рамки языка (undefined behavior)

Кстати, мне лень лезть в плюсовый стандарт, но вроде там что-то такое оговорено как раз применительно к signed/unsigned и битовым операциям. Просто может оговорено не достаточно четко применительно к арифметическим операциям. Ну и тонны работающего кода (с переполнением signed целых) не позволят включить такие проверки для существующих проектов, даже если в стандарте что-то четко пропишут.

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Пусть будет прерывание. Главное, что это не ручная проверка, расходующая такты и код.
Проверка есть, и такты она расходует одинаково как для прерывания, так и для перехода. Логику архитектуры x86 я уже подзабыл, но прагматика подсказывает что так оно и есть. А вот с кешем - да. Если проверять каждую арифметическую операцию, то КПД кеша уменьшится на неопределённую величину. А если проверять не каждую операцию (например, воспользоваться помощью компилятора, подсказывая ему какие переменные проверять), то КПД уменьшится на другую непоределённую величину.

ddn

  • Jr. Member
  • **
  • Сообщений: 59
    • Просмотр профиля
Насколько я понял, контроль переполнения включается установкой флага allchecks в константу defopt в модуле DevCompiler, его перекомпиляцией, и перезагрузкой самого БлэкБокс.

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

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Проверять переполнение или не проверять, определяется всецело условием задачи, а не соображениями производительности или экономии энергии. Условие задачи - вот истинная целесообразность.
Условие задачи всегда или почти всегда включает в себя требования по энергопотреблению. В частном, но не слишком частом, случае энергопотребление будет, по условию задачи, не ограничено.
Y = λf.(λx.f (x x)) (λx.f (x x))