Oberon space

General Category => Общий раздел => Тема начата: vlad от Декабрь 27, 2012, 04:59:43 pm

Название: А нужен ли в принципе контроль переполнения int типов
Отправлено: vlad от Декабрь 27, 2012, 04:59:43 pm
Сабж применительно к современному универсальному ЯП (и оберону в частности)? Потому как мороки с обходом такого контроля (см. параллельную ветку) может быть больше, чем пользы (поймать ошибку в арифметических вычислениях). Особенно если речь идет о чем-то довольно низкоуровневом типа О-7. Ну и сделать такие проверки эффективными довольно сложно (без наворачивания оптимизатора).
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: akron1 от Декабрь 27, 2012, 05:26:12 pm
Если как в C# (checked/unchecked), то вполне может быть.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: valexey_u от Декабрь 27, 2012, 05:37:57 pm
Сабж применительно к современному универсальному ЯП (и оберону в частности)? Потому как мороки с обходом такого контроля (см. параллельную ветку) может быть больше, чем пользы (поймать ошибку в арифметических вычислениях). Особенно если речь идет о чем-то довольно низкоуровневом типа О-7. Ну и сделать такие проверки эффективными довольно сложно (без наворачивания оптимизатора).
Я в x86 не разбираюсь, ибо быдла ниграмытныя, но вот в msp430, если мне склероз не изменяет, после арифметических операций можно смотреть статусные битики в R2, где как раз в том числе будет обозначено и переполнение.

Вопрос в том, что при этом самом переполнении делать. Мое IMHO - игнорировать по умолчанию, НО иметь в языке возможность явным образом воткнуть эту самую проверку. типа CHECK(a+b) для любых типов и по умолчанию проверять для всех операндов если их тип checked.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: Valery Solovey от Декабрь 27, 2012, 05:49:09 pm
в x86 такой флажок тоже есть
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: ilovb от Декабрь 27, 2012, 05:55:24 pm
Думаю, что проверка нужна только на этапе разработки/тестирования.
В релизе слишком накладно тупо каждое присваивание контролить.

ps Хотя зависит от задачи.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: Berserker от Декабрь 27, 2012, 05:59:45 pm
По умолчанию проверять, непроверяемые переменные помечать. С другой стороны, при переполнении в играх падать неприятно, что уж тут говорить. В таком случае можно в компиляторе предусмотреть вызов пользовательской процедуры, которая будет журналировать переполнение и только.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: vlad от Декабрь 28, 2012, 03:36:55 am
в x86 такой флажок тоже есть

Флажок проверять надо, а это медленно. Если б сразу исключение...
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: vlad от Декабрь 28, 2012, 03:41:37 am
По умолчанию проверять, непроверяемые переменные помечать.

Я, наверное, соглашусь. По умолчанию таки проверять. Хотя, конечно, несколько коробит, что банальный ++i будет оттранслирован в что-то более громоздкое, чем ассемблерный inc.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: trurl от Декабрь 28, 2012, 07:02:38 am
В x86 есть INTO - это должно быть не слишком накладно.
А в языке можно завести "модулярные" целые, которые проверять не надо.
var x: integer (mod 4294967296);
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: Kemet от Декабрь 28, 2012, 07:49:50 am
проще будет ввести модификатор блока, например
VAR i: LONGINT;
BEGIN[CHECHRANGE]
  i := MAX(LONGINT);
  INC(i);
END;
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: Berserker от Декабрь 28, 2012, 08:14:59 am
Переполнение может быт в тысячах мест. В тех же играх это ресурсы, характеристики, опыт и т.д. Весь код заполнить такими блоками не представляется целесообразным.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: Jordan от Декабрь 28, 2012, 08:18:35 am
проще будет ввести модификатор блока, например
VAR i: LONGINT;
BEGIN[CHECHRANGE]
  i := MAX(LONGINT);
  INC(i);
END;

Примерно так.

VAR i: LONGINT;
BEGIN
[CHECHRANGE = ON]
  i := MAX(LONGINT);
  INC(i);
[CHECHRANGE = OFF]
END;

Цель, убрать проверку полностью в программе и добавлять проверку в конкретном месте? К примеру при релизе, отключать проверку и перекомпилировать.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: Kemet от Декабрь 28, 2012, 08:42:56 am
вообще такие проверки малореальны - машинный код превратится в нечто невразумительное с кучей проверок и ветвлений, на суперскалярах, скорее всего, производительность существенно просядет
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: Geniepro от Декабрь 28, 2012, 09:39:49 am
В Аде (которую тут, походу, потихоньку изобретают) для этого есть специальные прагмы для компилятора:
http://en.wikibooks.org/wiki/Ada_Programming/Pragmas/Suppress
http://en.wikibooks.org/wiki/Ada_Programming/Pragmas/Unsuppress

procedure rangecheck_test is
   i: long_integer;
begin
   i := long_integer'Last;
   i := i + 1; -- тут предупреждения при компиляции
end rangecheck_test;
Builder results warning: value not in range of type "Standard.Long_Integer"
Builder results warning: "Constraint_Error" will be raised at run time

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

Вот наконец сделал нечто похожее:
with Text_IO, Ada.Integer_Text_IO; use Text_IO, Ada.Integer_Text_IO;

procedure rangecheck_test is
   procedure test (i: in out integer) is
   begin
      i := i + 1;
   end test;
   
   i: integer;
   
begin
   i := integer'Last;
   test(i);
   Put(i);
end rangecheck_test;
Здесь по умолчанию почему-то проверка переполнения отключается. Если включить прагмой
with Text_IO, Ada.Integer_Text_IO; use Text_IO, Ada.Integer_Text_IO;

procedure rangecheck_test is
   procedure test (i: in out integer) is
      pragma Unsuppress(Overflow_Check);
   begin
      i := i + 1;
   end test;
   
   i: integer;
   
begin
   i := integer'Last;
   test(i);
   Put(i);
end rangecheck_test;
то тогда при запуске сообщает об ошибке.

Ваще жесть эта Ада... о_О
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: trurl от Декабрь 28, 2012, 10:01:17 am
В x86 есть INTO - это должно быть не слишком накладно.
Посмотрел спецификацию, INTO жрет 3 такта, зараза. Лучше было бы как с плавающей точкой: выставил флаг и пусть прерывается при переполнении.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: trurl от Декабрь 28, 2012, 10:12:32 am
Вижу еще проблему. Каждый раз, встретив [CHECHRANGE = OFF] при чтении программы, будешь задумываться: а почему? То ли автор уверен, что переполнения не будет, то ли наоборот.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: valexey_u от Декабрь 28, 2012, 10:52:49 am
Да, и коль уж заговорили о переполнениях, выскажу старую свою мысль: система типов и у Оберона и у прочих современных ЯП (типа той же 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); Только программировать в таком стиле будет не слишком удобно.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: Geniepro от Декабрь 28, 2012, 11:38:19 am
Да, и коль уж заговорили о переполнениях, выскажу старую свою мысль: система типов и у Оберона и у прочих современных ЯП (типа той же java например, да и плюсов и haskell'я) - дырявая. У строго типизированных она почему-то запрещает например преобразование real->int, но при этом разрешает int+int. А ведь и то и другое может привести к одному и тому же - к переполнению/порче значения.
В Хаскелле есть же два вида целых чисел -- фиксированные Int и резиновые Integer.
Integer+Integer может привести к переполнению памяти, если закончится память у компьютера, но упомянутая в теме проблема не возникает.
С Int+Int ситуация немного другая. В Хаскелле считается, что Int -- это по сути перечисление целых чисел, замкнутых по кругу, и если сложить max_int и 1, то получим min_int, а не переполнение. То есть тоже проблемы вроде как нет...
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: Berserker от Декабрь 28, 2012, 12:03:56 pm
То есть никаких проверок + отдельно классы длинных чисел. Ничего нового.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: Valery Solovey от Декабрь 28, 2012, 12:53:36 pm
в x86 такой флажок тоже есть

Флажок проверять надо, а это медленно. Если б сразу исключение...
Какое такое исключение? На уровне процессора? Спасибоненадо. А чтобы его бросить проверка всё равно нужна. Так что исклчение не медленнее условного перехода по этому флажку, стоящему сразу за арифметической операцией (есть, кажется, такой в системе команд).
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: valexey_u от Декабрь 28, 2012, 01:42:50 pm
в x86 такой флажок тоже есть

Флажок проверять надо, а это медленно. Если б сразу исключение...
Какое такое исключение? На уровне процессора? Спасибоненадо. А чтобы его бросить проверка всё равно нужна. Так что исклчение не медленнее условного перехода по этому флажку, стоящему сразу за арифметической операцией (есть, кажется, такой в системе команд).
Иногда процессор умеет при переполнении дергать за прерывание если все правильно сконфигурировано.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: vlad от Декабрь 28, 2012, 02:58:20 pm
Флажок проверять надо, а это медленно. Если б сразу исключение...
Какое такое исключение? На уровне процессора? Спасибоненадо. А чтобы его бросить проверка всё равно нужна. Так что исклчение не медленнее условного перехода по этому флажку, стоящему сразу за арифметической операцией (есть, кажется, такой в системе команд).

А то, что при обращении к нулевому указателю возникает исключение на уровне процессора - тебя не смущает? :) И ты уверен, что тупая проверка каждый раз перед таким обращением будет "не медленнее" (не говоря про объем кода, который в свою очередь влезает/не влезает в кеш)?
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: valexey_u от Декабрь 28, 2012, 03:08:28 pm
Флажок проверять надо, а это медленно. Если б сразу исключение...
Какое такое исключение? На уровне процессора? Спасибоненадо. А чтобы его бросить проверка всё равно нужна. Так что исклчение не медленнее условного перехода по этому флажку, стоящему сразу за арифметической операцией (есть, кажется, такой в системе команд).

А то, что при обращении к нулевому указателю возникает исключение на уровне процессора - тебя не смущает? :) И ты уверен, что тупая проверка каждый раз перед таким обращением будет "не медленнее" (не говоря про объем кода, который в свою очередь влезает/не влезает в кеш)?
По моему, в данном случае корректней говорить о прерывании нежели о каком-то там исключении на уровне процессора.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: vlad от Декабрь 28, 2012, 03:16:06 pm
По моему, в данном случае корректней говорить о прерывании нежели о каком-то там исключении на уровне процессора.

Пусть будет прерывание. Главное, что это не ручная проверка, расходующая такты и код.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: valexey_u от Декабрь 28, 2012, 03:18:53 pm
По моему, в данном случае корректней говорить о прерывании нежели о каком-то там исключении на уровне процессора.

Пусть будет прерывание. Главное, что это не ручная проверка, расходующая такты и код.
С другой стороны, такое решение все равно будет расходовать например энергию, что в ряде случаев критично. Поэтому целесообразность всегда и везде проверять переполнение все же под сомнением.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: vlad от Декабрь 28, 2012, 03:33:19 pm
С другой стороны, такое решение все равно будет расходовать например энергию, что в ряде случаев критично. Поэтому целесообразность всегда и везде проверять переполнение все же под сомнением.

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

Кстати, мне лень лезть в плюсовый стандарт, но вроде там что-то такое оговорено как раз применительно к signed/unsigned и битовым операциям. Просто может оговорено не достаточно четко применительно к арифметическим операциям. Ну и тонны работающего кода (с переполнением signed целых) не позволят включить такие проверки для существующих проектов, даже если в стандарте что-то четко пропишут.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: Valery Solovey от Декабрь 29, 2012, 02:43:20 pm
Пусть будет прерывание. Главное, что это не ручная проверка, расходующая такты и код.
Проверка есть, и такты она расходует одинаково как для прерывания, так и для перехода. Логику архитектуры x86 я уже подзабыл, но прагматика подсказывает что так оно и есть. А вот с кешем - да. Если проверять каждую арифметическую операцию, то КПД кеша уменьшится на неопределённую величину. А если проверять не каждую операцию (например, воспользоваться помощью компилятора, подсказывая ему какие переменные проверять), то КПД уменьшится на другую непоределённую величину.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: ddn от Январь 03, 2013, 12:46:12 am
Насколько я понял, контроль переполнения включается установкой флага allchecks в константу defopt в модуле DevCompiler, его перекомпиляцией, и перезагрузкой самого БлэкБокс.

вообще такие проверки малореальны - машинный код превратится в нечто невразумительное с кучей проверок и ветвлений, на суперскалярах, скорее всего, производительность существенно просядет
...
С другой стороны, такое решение все равно будет расходовать например энергию, что в ряде случаев критично. Поэтому целесообразность всегда и везде проверять переполнение все же под сомнением.
Проверять переполнение или не проверять, определяется всецело условием задачи, а не соображениями производительности или экономии энергии. Условие задачи - вот истинная целесообразность.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: valexey_u от Январь 03, 2013, 12:53:16 am
Проверять переполнение или не проверять, определяется всецело условием задачи, а не соображениями производительности или экономии энергии. Условие задачи - вот истинная целесообразность.
Условие задачи всегда или почти всегда включает в себя требования по энергопотреблению. В частном, но не слишком частом, случае энергопотребление будет, по условию задачи, не ограничено.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: ddn от Январь 03, 2013, 01:22:51 am
Условие задачи всегда или почти всегда включает в себя требования по энергопотреблению. В частном, но не слишком частом, случае энергопотребление будет, по условию задачи, не ограничено.
А требование обработки данных по вполне конкретному принципу (по модулю либо с переполнением) условие задачи включает? Вам же не все равно, как данные будут обработаны, правильно или неправильно?

Если требования по энергопотреблению сводятся к его минимизации, то такая минимизация должна происходить в рамках прочих условий, правильной обработки данных например. Если требуется чтобы энергопотребление не превышало заданной величины, то данные опять же должны быть обработаны правильно, но такие условия задачи могут оказаться несовместными, и тогда программа не скомпилируется/не загрузится/будет нарушать условия задачи при работе.
Название: Re: А нужен ли в принципе контроль переполнения int типов
Отправлено: ddn от Январь 03, 2013, 07:30:21 am
Да, и коль уж заговорили о переполнениях, выскажу старую свою мысль: система типов и у Оберона и у прочих современных ЯП (типа той же java например, да и плюсов и haskell'я) - дырявая.
Переполнения никак не связаны с типизацией, они связаны с реализацией математических операций и функций в ЯП. Переполнение, с высокоуровневой точки зрения, это изменение результата ЯП-операции или функции с математически правильного значения, если это значение выходит за пределы диапазона типа результата, на математически неправильное значение, но взятого в пределах указанного диапазона. Обычно это усечение старших битов.

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

У строго типизированных она почему-то запрещает например преобразование real->int, но при этом разрешает int+int.
Так int+int это не преобразование, а операция.

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

Пусть у нас есть тип Int(N), где N - битность этого целочисленного типа.
Разные значения одного типа (одного объекта) не обязаны иметь одинаковую битность в машинном представлении. Значения одного типа это высокоуровневая категория и не привязаны к месту в памяти и ее размеру.

Тогда, очевидно в случае сложения двух чисел этого типа результат не будет иметь тип Int(N), он будет иметь тип Int(N+1).
При том условии, что не накладывается других ограничений кроме типа на значения аргументов, т.е. операция является всюду определенной. И если имеется подобная иерархия типов со вложенными диапазонами, не обязательно основанная на числе бит в представлении.
Тогда можно ввести правило "тип результата = минимальный тип, содержащий значение результата операции при любых допустимых значениях аргументов из диапазонов их типа", который вы назвали логическим типом.

Вообще же говоря (без такого правила), множество значений не привязано к определенному диапазонному типу. Потому невозможно определить тип результата по множеству принимаемых им значений, тип результата назначается. Произвольно. Операции INTEGER + INTEGER можно назначить тип результата хоть BYTE. Правда, операция не обязательно будет всюду определена.

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

Либо требовать рукотворного явного приведения типов. Типа a,b,c,d : int_4; a:=int_4(a+b+c+d); Только программировать в таком стиле будет не слишком удобно.
Что здесь имеется ввиду?
1. Тип результата операций опредялется по правилу "минимального типа", а затем функция int_4 проецирует (с проверкой) значение выражения к типу int_4.
2. int_4( + + + ) - единая конструкция (вызов функции), где роль разделителя аргуметов играет знак '+' (вместо запятой).
3. int_4 - опция компилятора, которая задает тип результата всех арифметических операций в подставленном выражении.
Отличаются тем, где генерируется ошибка.