Pratique unique la plus efficace pour prévenir les débordements et dépassements arithmétiques

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

Question

Quelle est la pratique la plus efficace pour prévenir les débordement arithmétique et débordement ?

Certains exemples me viennent à l’esprit:

  • test basé sur des plages d'entrée valides
  • validation à l'aide de méthodes formelles
  • utilisation d'invariants
  • détection lors de l'exécution à l'aide de fonctionnalités de langage ou de bibliothèques (cela ne l'empêche pas)
Était-ce utile?

La solution

Une possibilité consiste à utiliser un langage comportant des entiers arbitrairement dimensionnés qui ne débordent ni ne débordent jamais.

Sinon, si cela vous préoccupe vraiment et si votre langage le permet, écrivez une classe wrapper qui se comporte comme un entier, mais vérifie le dépassement des capacités de chaque opération. Vous pourriez même le faire vérifier les versions de débogage et laisser les choses optimisées pour les versions. Vous pouvez le faire dans un langage tel que C ++, qui se comporterait presque exactement comme un entier pour les versions de version, mais pour les versions de débogage, vous obtiendrez une vérification complète de l'exécution.

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

Modifier:

Il s'avère que quelqu'un le fait déjà pour C ++ - l'implémentation actuelle est axée sur Visual Studio. mais on dirait qu'ils obtiennent également un soutien pour gcc.

Autres conseils

J'écris beaucoup de code de test pour effectuer une vérification de plage / validité sur mon code. Cela tend à attraper la plupart de ces types de situations - et m'aide définitivement à écrire davantage de code à l'épreuve des balles.

Utilisez des nombres à virgule flottante de haute précision, comme un double long .

Je pense qu'il vous manque une option très importante dans votre liste: choisissez le bon langage de programmation pour le travail. De nombreux langages de programmation ne rencontrent pas ces problèmes, car ils ne possèdent pas de nombres entiers de taille fixe.

Lors du choix de la langue que vous utilisez, la considération de la taille de l'entier est plus importante. Vérifiez simplement votre saisie si vous ne savez pas si la valeur est dans les limites, ou utilisez la gestion des exceptions si le cas est extrêmement rare.

Un wrapper qui vérifie les incohérences aura du sens dans de nombreux cas. Si une opération additive (c'est-à-dire une addition ou une multiplication) sur deux ou plusieurs entiers donne une valeur inférieure à celle des opérandes, alors vous savez que quelque chose s'est mal passé. Chaque opération additive doit être suivie de,

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

De même, toute opération qui devrait logiquement aboutir à une valeur inférieure doit être vérifiée pour voir si elle a été accidentellement imbriquée.

Avez-vous étudié la possibilité d'utiliser des méthodes formelles pour vérifier votre code et prouver qu'il est exempt de débordements? Une technique formelle connue sous le nom d'interprétation abstraite peut vérifier la robustesse de votre logiciel pour prouver que celui-ci ne souffrira pas d'un débordement, d'un débordement, d'une division par zéro, d'un débordement ou de toute autre erreur d'exécution similaire. C'est une technique mathématique qui analyse de manière exhaustive votre logiciel. Patrick Cousot a été le pionnier de la technique dans les années 1970. Il a été utilisé avec succès pour diagnostiquer un débordement dans la fusée Arian 5, où un débordement a provoqué la destruction du lanceur. Le débordement a été provoqué lors de la conversion d'un nombre à virgule flottante en entier. Pour plus d'informations sur cette technique, cliquez ici et sur Wikipedia .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top