human
Pourquoi le logiciel a-t-il des bugs ? Je comprends qu'un système d'exploitation comme Windows a beaucoup de code écrit, mais il y a des milliers de personnes qui travaillent dessus et je suppose qu'il y a des bases qui ont été codées et revues plusieurs fois. Explique comme si j'avais cinq ans.
gpt
Permettez-moi de vous donner un exemple rapide : if (someNumber < 10) foo( ) ; si (unNombre > 10) barre ( ) ; Repérer le bogue ? Que fait-on si un nombre * vaut * 10 ? Nous avons raté cette affaire. Réparons-le : if (someNumber <= 10) foo (); si (unNombre > 10) barre ( ) ; C'était pourtant facile. Essayons quelque chose d'un peu plus difficile. entier x = 10 ; entier y = 2,5 ; int z = x + y ; Quelle est la valeur de z ? Vous penseriez que c'est 12,5 , n'est - ce pas ? C'est faux . Il est 12h. Quel est le bogue ? Eh bien, ici, nous avons fait une erreur dans le choix de nos types de données. Un " int " est un entier primitif , qui ne peut * que * être des nombres entiers ( c'est la définition d' un entier , après tout ) . Et si nous utilisions des types de données plus compliqués , comme un double ou un flottant , qui * prennent * en charge les nombres fractionnaires . Essayons ça , alors . entier x = 10 ; y double = 2,5 ; int z = x + y ; Attendez , cela ne fait toujours que z = 12 . y peut être un double , mais z n'est pas . Réparons-le à nouveau. entier x = 10 ; y double = 2,5 ; double z = x + y ; Nous l'avons corrigé, enfin. Sauf que nous ne l'avons peut-être pas fait. Certains langages transcrivent les types lors de l'arithmétique. Puisque nous faisons x + y , les résultats peuvent être transformés en un entier avant d' être assignés à z , puisque x était le premier paramètre . Donc z peut être 12 , ou 12,5 , selon la façon dont le langage particulier gère les mathématiques . Certes , la plupart des langages gèreront cela comme prévu , et z sera égal à 12,5 . Soyons encore plus difficiles : // le tampon est l'endroit où nous stockons temporairement les touches sur lesquelles l'utilisateur appuie. C'est ce qu'on appelle un « tableau » et vous permet de stocker plusieurs éléments au même endroit. Cela fonctionne comme ceci : si je stocke ' H ' ' E ' ' L ' ' L ' et ' O ' dans buffer , buffer[0 ] est l'emplacement de ' H ' , buffer[1 ] est l'emplacement de ' E ' , etc . // charactersSoFar est le nombre de caractères que l'utilisateur a saisis jusqu'à présent . C'est ainsi que nous pouvons trouver le bon endroit dans le tampon pour placer le nouveau caractère . // keypress est la touche sur laquelle l'utilisateur vient d'appuyer . captureKeypress(char [ ] buffer , int charactersSoFar , char keypress ) { // Si nous avons tapé autant de caractères que le buffer peut en contenir, nous devons agrandir le buffer (nous doublons sa taille) if ( buffer.size = = charactersSoFar ) buffer = char[buffer.size * 2 ] ; // Si la touche est un caractère valide, nous l'ajoutons à la fin du tampon et incrémentons le compteur de caractèresSoFar if (isValidCharacter(keypress)) { buffer[charactersSoFar ] = keypress charactersSoFar++ ; } // Si la touche est un retour arrière, décrémente le compteur charactersSoFar et supprime cette touche (en l'écrasant avec le caractère nul \0) if (isBackspace(keypress)) { charactersSoFar--; buffer[charactersSoFar ] = ' \0 ' ; } } Quel est le bogue ici ? Celui-ci est un peu plus délicat. Beaucoup plus subtil. En fait, c'était si subtil qu'un bogue de ce genre a été corrigé dans le chargeur de démarrage Grub il y a deux ans (un outil populaire pour installer Linux/plusieurs systèmes d'exploitation), après des années d'existence. Regardez ce qui se passe lorsque nous ajoutons des caractères à notre buffer . S'il devient trop gros , nous le agrandissons . S'il commence avec un espace pour 8 caractères et que nous tapons " Password123 " , dès que nous tapons ' 1 ' , il deviendra assez grand pour 16 caractères , et nous continuons à incrémenter notre variable " characters SoFar " pour garder une trace du nombre les personnages sont actuellement dans notre tampon . Regardez ce qui se passe lorsque nous *supprimons* des caractères. Disons que vous tapez " Test " . caractèresSoFar sera 4 . Ensuite, nous appuyons sur retour arrière . Maintenant notre tampon a " Tes " et charactersSoFar sera 3 . Que se passe-t-il lorsque vous appuyez sur retour arrière 10 fois de plus ? Maintenant, votre tampon n'a rien dedans, et charactersSoFar sera -7. Que se passera-t-il lorsque vous taperez à nouveau ? Avant d'en arriver là, j'ai besoin d'expliquer comment fonctionnent les tableaux. buffer est un tableau , qui est une façon originale de dire une adresse mémoire indexée . Lorsque vous créez un tableau, l'ordinateur vous donne une adresse en mémoire (disons, x100). Ensuite, lorsque vous mettez quelque chose dans buffer[0 ] , il est en fait mis dans x100 , et lorsque vous mettez quelque chose dans buffer[1 ] , il est en fait mis dans x101 . Retour à notre tampon lorsque nous appuyons trop souvent sur la touche de retour arrière . Que se passe-t-il lorsque vous mettez quelque chose dans buffer[-7 ] alors ? Eh bien, la même chose. Il est placé dans x093 , qui est la mémoire que quelque chose d' autre dans votre programme utilisait probablement . Appuyez suffisamment de fois sur la touche de retour arrière et vous pourrez supprimer tout ce qui se trouve en mémoire avant l'endroit où votre tampon est stocké. Cette vulnérabilité existait dans Grub depuis longtemps, et si vous appuyiez suffisamment de fois sur la touche de retour arrière, cela supprimerait certaines choses en mémoire qui empêchaient l'accès à l'ordinateur de quelqu'un, et permettrait à un utilisateur malveillant de prendre le contrôle de votre ordinateur sans votre mot de passe. tl;dr Les bogues informatiques peuvent être très, très subtils, et plus il y a de personnes qui y travaillent, plus il y a de risques de mauvaise communication ou de malentendu. Souvenez-vous du moment où votre enseignant du primaire vous a dit d'écrire des instructions sur « comment faire un sandwich au beurre d'arachide et à la gelée ». C'est fondamentalement comme ça , mais beaucoup plus difficile .