En 1989, Felix Lee, John Hayes et Angela Thomas ont écrit un test de Hacker prenant la forme d'un quiz avec de nombreuses blagues d'initiés, comme « Mangez-vous des moisissures visqueuses? "
J'envisage la série suivante:
0015 Ever change the value of 4?
0016 ... Unintentionally?
0017 ... In a language other than Fortran?
Y a-t-il une anecdote particulière qui rend le nombre «4» particulier dans la série?
Une implémentation de Fortran a-t-elle permis de modifier la valeur des constantes? Était-ce possible dans d'autres langues couramment utilisées à l'époque?
4
pour5
dans les listes d'entiers internes.4 = 5
était possible.Réponses:
Autrefois (dans les années 1970 et avant), certains ordinateurs n'avaient pas de MMU (et cela est vrai aujourd'hui pour les microcontrôleurs très bon marché).
Sur de tels systèmes, il n'y a pas de protection de la mémoire donc pas de segment en lecture seule dans l' espace d'adressage , et un programme buggy pourrait écraser une constante (soit dans la mémoire de données, soit même à l'intérieur du code machine).
Les compilateurs Fortran à cette époque ont passé des arguments formels par référence . Donc, si vous l'avez fait
CALL FUN(4)
et queSUBROUTINE FUN(I)
son corps changeI
- par exemple avec une déclarationI = I + 1
dans son corps, vous pourriez avoir une catastrophe, changer 4 en 5 dans l'appelant (ou pire).Cela était également vrai sur les premiers micro-ordinateurs comme l' IBM PC AT original de 1984, avec MS-DOS
FWIW, je suis assez vieux pour avoir utilisé, à l'adolescence au début des années 1970, de tels ordinateurs: IBM1620 et CAB500 (dans un musée: ce sont des ordinateurs de l'époque des années 1960!). L'IBM1620 était assez amusant: il était utilisé dans les tables de mémoire pour les ajouts et les multiplications (et si vous écrasiez ces tables, le chaos s'ensuivait). Ainsi, non seulement vous pourriez écraser un 4, mais vous pourriez même écraser chaque futur ajout 2 + 2 ou multiplications 7 * 8 (mais j'ai vraiment oublié ces détails sales, donc cela pourrait être faux).
Aujourd'hui, vous pouvez remplacer le code BIOS dans la mémoire flash, si vous persévérez suffisamment. Malheureusement, je ne me sens plus aussi amusant, donc je n'ai jamais essayé. (J'ai même peur d'installer des LinuxBios sur ma carte mère).
Sur les ordinateurs et systèmes d'exploitation actuels, le fait de passer une constante par référence et de la modifier à l'intérieur de l'appelé provoquera simplement une violation de segmentation , ce qui semble familier à de nombreux développeurs C ou C ++.
BTW: être tatillonne: l'écrasement 4 n'est pas une question de langage, mais d'implémentation.
la source
gfortran
. Les constantes sont placées dans leur segment et transmises par référence à un sous-programme. Par défaut, la section constante est en lecture seule, donc une erreur de protection de la mémoire tue le programme.Il s'agissait d'un effet secondaire non intentionnel de la stratégie d'évaluation des appels de fonction de FORTRAN en combinaison avec une optimisation du compilateur erronée.
FORTRAN II a introduit des fonctions et sous-programmes définis par l'utilisateur avec leurs arguments passés par référence . (Eh bien, je ne sais pas. C'était probablement plus efficace que le passage par valeur sur le matériel IBM de l'époque.)
Normalement, le passage par référence signifie que vous devez passer une valeur l (comme une variable) au lieu d'une valeur r. Mais les concepteurs de FORTRAN ont décidé d'être utiles et de vous laisser passer des valeurs r comme arguments de toute façon. Le compilateur générerait automatiquement une variable pour vous. Donc, si vous avez écrit:
le compilateur convertirait cela dans les coulisses en quelque chose comme
Il y avait également une optimisation de compilateur commune appelée «pool littéral», qui consoliderait plusieurs instances de la même constante numérique dans la même variable générée automatiquement. (Plusieurs langues de la famille C l'exigent pour les littéraux de chaîne.) Donc, si vous avez écrit
ce serait traité comme si c'était
ce qui semble être une chose parfaitement raisonnable à faire jusqu'à ce que vous ayez un sous-programme qui modifie la valeur de ses paramètres.
Boom!
CALL SUBBAR(4)
changé la valeur du 4 dans le pool littéral en 5. Et puis vous vous demandez pourquoiSUBBAZ
suppose que vous l'avez passé un 5 au lieu de ce que4
vous avez réellement écrit dans le code.Les versions plus récentes de Fortran atténuent ce problème en vous permettant de déclarer la
INTENT
variable commeIN
ouOUT
, et en vous donnant une erreur (ou au moins un avertissement) si vous passez une constante enOUT
paramètre.la source
Dans FORTRAN, lorsqu'une constante est passée à une autre procédure, elle n'est plus protégée. C'est à cela qu'ils se réfèrent. D'autres langages de programmation populaires à la même époque étaient C et Pascal qui n'avaient pas (et n'ont toujours pas) ce problème. Peut-être existe-t-il des langages de programmation plus anciens que je ne connais pas qui ont le même problème.
la source
.rodata
segment en lecture seule (comme le font les compilateurs actuels), il ne modifiera pas la constante mais entraînerait un SEGV.