Pregunta

¿Cuál es la práctica más eficaz para prevenir desbordamiento aritmético y desbordamiento?

Algunos ejemplos que me vienen a la mente son:

  • pruebas basadas en rangos de entrada válidos
  • validación utilizando métodos formales
  • uso de invariantes
  • detección en tiempo de ejecución utilizando funciones o bibliotecas del lenguaje (esto no lo impide)
¿Fue útil?

Solución

Una posibilidad es utilizar un lenguaje que tenga números enteros de tamaño arbitrario que nunca se desborden o no se desborden.

De lo contrario, si esto es algo que realmente le preocupa, y si su idioma lo permite, escriba una clase contenedora que actúe como un número entero, pero verifique que cada operación no se desborde.Incluso podría hacer que verifique las compilaciones de depuración y deje las cosas optimizadas para las compilaciones de lanzamiento.En un lenguaje como C++, podría hacer esto y se comportaría casi exactamente como un número entero para las compilaciones de lanzamiento, pero para las compilaciones de depuración obtendría una verificación completa del tiempo de ejecución.

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...
};

Editar:

Resulta que alguien es haciendo esto ya para C++ - La implementación actual está enfocada a Visual Studio, pero parece que también recibirán soporte para gcc.

Otros consejos

Escribo una gran cantidad de código de prueba para verificar el rango/validez de mi código.Esto tiende a detectar la mayoría de estos tipos de situaciones y definitivamente me ayuda a escribir un código más seguro.

Utilice números de punto flotante de alta precisión como un doble largo.

Creo que te falta una opción muy importante en tu lista:Elija el lenguaje de programación adecuado para el trabajo.Hay muchos lenguajes de programación que no tienen estos problemas porque no tienen números enteros de tamaño fijo.

Hay consideraciones más importantes a la hora de elegir qué idioma utilizar que el tamaño del número entero.Simplemente verifique su entrada si no sabe si el valor está dentro de los límites, o use el manejo de excepciones si el caso es extremadamente raro.

Un contenedor que verifique inconsistencias tendrá sentido en muchos casos.Si una operación aditiva (es decir, suma o multiplicación) en dos o más números enteros da como resultado un valor menor que los operandos, entonces sabrá que algo salió mal.Cada operación aditiva debe ser seguida por,

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

Del mismo modo, se debe verificar cualquier operación que lógicamente deba resultar en un valor menor para ver si se embiggin accidentalmente.

¿Ha investigado el uso de métodos formales para verificar su código y demostrar que está libre de desbordamientos?Una técnica de métodos formales conocida como interpretación abstracta puede verificar la solidez de su software para demostrar que no sufrirá un desbordamiento, un desbordamiento insuficiente, una división por cero, un desbordamiento u otro error de tiempo de ejecución similar.Es una técnica matemática que analiza exhaustivamente tu software.Patrick Cousot fue pionero en esta técnica en la década de 1970.Se utilizó con éxito para diagnosticar una condición de desbordamiento en el cohete Arian 5, donde un desbordamiento provocó la destrucción del vehículo de lanzamiento.El desbordamiento se produjo al convertir un número de punto flotante en un número entero.Puedes encontrar más información sobre esta técnica. aquí y también en Wikipedia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top