48 votes

Pourquoi les langues ne provoquent-elles pas d'erreurs sur le dépassement d'entier par défaut?

Dans plusieurs langages de programmation modernes (y compris C++, Java et C#), le langage permet de dépassement d'entier pour se produire lors de l'exécution sans lever toute sorte de condition d'erreur.

Prenons l'exemple de cette (fictive) C#, qui ne tient pas compte de la possibilité de dépassement de capacité/underflow. (Par souci de concision, la méthode ne gère pas le cas où la liste est référence null.)

//Returns the sum of the values in the specified list.
private static int sumList(List<int> list)
{
    int sum = 0;
    foreach (int listItem in list)
    {
        sum += listItem;
    }
    return sum;
}

Si cette méthode est appelée comme suit:

List<int> list = new List<int>();
list.Add(2000000000);
list.Add(2000000000);
int sum = sumList(list);

Un dépassement de capacité se fera dans le sumList (), méthode (parce que le "int" type en C# est un entier signé 32 bits, et la somme des valeurs dans la liste dépasse la valeur maximale de 32 bits entier signé). La somme de la variable aura une valeur de -294967296 (pas une valeur de 4000000000); ce n'est probablement pas ce que les (hypothétiques) développeur de la sumList méthode destinée.

Évidemment, il existe différentes techniques qui peuvent être utilisées par les développeurs pour éviter la possibilité d'un dépassement d'entier, comme l'utilisation d'un type comme Java BigInteger, ou le vérifiée mot-clé et /vérifié commutateur de compilateur en C#.

Cependant, la question qui m'intéresse est pourquoi ces langues ont été conçus par défaut permettent aux débordements d'entiers de se produire en premier lieu, au lieu de, par exemple, le déclenchement d'une exception lorsqu'une opération est effectuée à l'exécution qui provoque un dépassement de capacité. Il semble que ce type de comportement permettrait d'éviter des bugs dans les cas où un développeur néglige de tenir compte de la possibilité de dépassement de capacité lors de l'écriture du code qui effectue une opération arithmétique qui pourrait entraîner un dépassement de capacité. (Ces langues pourraient avoir compris quelque chose comme un "unchecked" mot-clé qui pourrait désigner un bloc entier où le dépassement est autorisé à se produire, sans exception, dans les cas où ce comportement est explicitement prévu par le développeur, le C# en fait n'ont de ce.)

La réponse n'envisagent performance -- la langue concepteurs ne veulent pas que leurs langues respectives à défaut d'avoir "lente" de l'arithmétique entier des opérations par lesquelles l'exécution aurait besoin de faire du travail supplémentaire pour vérifier si un dépassement de capacité s'est produite, sur chaque applicable opération arithmétique -- et ce facteur de performance, a dépassé la valeur d'éviter le "silence" des échecs dans le cas d'un débordement involontaire se produit?

Existe-il d'autres raisons pour cette langue décision de conception ainsi, autres que des considérations de performance?

41voto

Jay Bazuzi Points 20462

En C#, c'était une question de performance. Plus précisément, out-of-box de l'analyse comparative.

Quand C# a été de nouvelles, Microsoft espérais beaucoup de développeurs C++ serait passer. Ils savaient que beaucoup de C++ les gens pensé de C++ comme étant rapide, surtout plus rapide que les langues que "perdu" du temps sur la gestion automatique de la mémoire et la comme.

Les deux adoptants potentiels et magazine évaluateurs peuvent obtenir une copie de la nouvelle C#, l'installer, construire une banale application que personne ne serait jamais écrire dans le monde réel, l'exécuter dans une boucle serrée, et de mesurer combien de temps il a fallu. Alors qu'ils avaient une décision en faveur de leur entreprise ou de publier un article en fonction de ce résultat.

Le fait que leur test ont montré C# à être plus lent que nativement compilée en C++ est le genre de chose qui serait à son tour les gens de C# rapidement. Le fait que votre application en C# va attraper débordement/underflow automatiquement est le genre de chose qu'ils pourraient manquer. Donc, elle est désactivée par défaut.

Je pense qu'il est évident que 99% du temps, nous voulons /vérifié pour être sur. C'est un triste compromis.

26voto

David Hill Points 2423

Je pense que la performance est une très bonne raison. Si vous considérez chaque instruction dans un programme typique qui incrémente un entier, et si au lieu de l'opération simple d'ajouter 1, il devait vérifier chaque fois si l'ajout de 1 déborderait le type, le coût en cycles supplémentaires serait plutôt sévère.

16voto

Doug T. Points 33360

Vous travaillez sous l'hypothèse que le débordement d'entier est toujours un comportement indésirable.

Parfois débordement d'entier est le comportement souhaité. Un exemple que j'ai vu est la représentation d'une absolue de la valeur de position fixe nombre de point. Étant donné un unsigned int, 0 est 0 ou 360 ° et le max de 32 bits entier non signé(0xffffffff)est la plus grande valeur juste en dessous de 360 degrés.

int main()
{
    uint32_t shipsHeadingInDegrees= 0;

    // Rotate by a bunch of degrees
    shipsHeadingInDegrees+= 0x80000000; // 180 degrees
    shipsHeadingInDegrees+= 0x80000000; // another 180 degrees, overflows 
    shipsHeadingInDegrees+= 0x80000000; // another 180 degrees

    // Ships heading now will be 180 degrees
    cout << "Ships Heading Is" << (double(shipsHeadingInDegrees) / double(0xffffffff)) * 360.0 << std::endl;

}

Il y a probablement d'autres situations où le débordement est acceptable, semblable à cet exemple.

8voto

Steve Jessop Points 166970

C/C++ ne jamais mandat piège de comportement. Même l'évidence de la division par 0 n'est pas défini comportement en C++, pas un certain type de piège.

Le langage C n'ont pas de concept de la trappe, sauf si vous comptez les signaux.

C++ est un principe de conception qu'il n'introduisent pas de frais généraux n'est pas présent dans C, sauf si vous le demandez. Donc Stroustrup n'aurait pas voulu mandat entiers se comporter d'une manière qui exige que toute explicite de la vérification.

Certains des premiers compilateurs, léger et implémentations restreinte du matériel, ne prennent pas en charge les exceptions à tout, et des exceptions peuvent souvent être désactivé à l'aide des options du compilateur. Régie d'exceptions de la langue built-ins serait problématique.

Même si le C++ avait fait des entiers cochée, 99% des programmeurs dans les premiers jours aurait fait de si loin pour le boost de performance...

6voto

Rob Walker Points 25840

C'est probablement 99% de performance. Sur x86, il faudrait vérifier l’indicateur de débordement à chaque opération, ce qui serait un énorme problème de performances.

Les 1% restants couvriraient les cas où les gens font des manipulations sophistiquées ou sont «imprécis» dans le mélange d'opérations signées et non signées et veulent la sémantique de débordement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X