Единственный наиболее эффективный метод предотвращения арифметического переполнения и потери значения.

StackOverflow https://stackoverflow.com/questions/78913

Вопрос

Какова самая эффективная практика предотвращения арифметическое переполнение и перелив?

Вот некоторые примеры, которые приходят на ум:

  • тестирование на основе допустимых входных диапазонов
  • проверка с использованием формальных методов
  • использование инвариантов
  • обнаружение во время выполнения с использованием языковых функций или библиотек (это не предотвращает его)
Это было полезно?

Решение

Одна из возможностей — использовать язык, в котором есть целые числа произвольного размера, которые никогда не переполняются/не переполняются.

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

class CheckedInt
{
private: 
    int Value;

public:
    // Constructor
    CheckedInt(int src) : Value(src) {}

    // Conversions back to int
    operator int&() { return Value; }
    operator const int &() const { return Value; }

    // Operators
    CheckedInt operator+(CheckedInt rhs) const
    {
        if (rhs.Value < 0 && rhs.Value + Value > Value)
            throw OverflowException();
        if (rhs.Value > 0 && rhs.Value + Value < Value)
            throw OverflowException();
        return CheckedInt(rhs.Value + Value);
    }

    // Lots more operators...
};

Редактировать:

Оказывается, кто-то делаю это уже для C++ — текущая реализация ориентирована на Visual Studio, но похоже, что они также получают поддержку gcc.

Другие советы

Я пишу много тестового кода для проверки диапазона/валидности моего кода.Это помогает уловить большинство подобных ситуаций и определенно помогает мне писать более надежный код.

Используйте числа с плавающей запятой высокой точности, например длинный двойной.

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

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

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

if (sum < operand1 || sum < operand2)
    omg_error();

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

Исследовали ли вы использование формальных методов для проверки вашего кода на отсутствие переполнений?Метод формальных методов, известный как абстрактная интерпретация, может проверить надежность вашего программного обеспечения, чтобы доказать, что ваше программное обеспечение не будет страдать от переполнения, потери значения, деления на ноль, переполнения или других подобных ошибок во время выполнения.Это математический метод, который тщательно анализирует ваше программное обеспечение.Эту технику впервые применил Патрик Кузо в 1970-х годах.Его успешно использовали для диагностики состояния перелива в ракете «Ариан-5», когда перелив привел к разрушению ракеты-носителя.Переполнение произошло при преобразовании числа с плавающей запятой в целое число.Более подробную информацию об этой технике вы можете найти здесь а также на Википедия.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top