Pire que goto ?
Par Emmanuel Deloget, mardi 26 février 2008 à 17:00 :: Expériences :: permalien #116
Tags: code dangereux, fortran
Je ne pensais pas vraiment cela possible (même si, dans mon expérience, j'ai vu des morceaux de code dont la pertinence n'avait d'égal que la régularité avec laquelle ils ne fonctionnaient pas), mais j'ai trouvé une construction de code qui a le mérite d'être :
- illisible
- dangereuse
- génératrice d'exceptions
Le tout, sans utiliser de goto.
Il faut revenir à l'ancien temps pour trouver le responsable, et notamment se replonger dans les affres d'un langage qui devient de nos jours aussi ésotérique que le Klingon : j'ai dénommé Fortran, sous sa forme normalisée en 1977 (j'avais 1 an. Argh.). Pour être honnète, je ne prétends pas comprendre la philosophie du langage lui même : il s'agit d'un langage impératif, vaguement fortement typé, et globalement illisible.
Mais revenons à notre problème principale : cette construction de code qui a tant de défauts.
Au début, il y a une bonne intention : simplifier la lecture et l'écriture dans les fichiers. Une fois un fichier ouvert, on peut se contenter d'un seul READ pour lire tout le contenu d'un fichier binaire. Un exemple :
OPEN(UNIT=1,
1 FILE='mon_fichier.dat',
1 STATUS='OLD',
1 FORM='UNFORMATTED'
1 ACCESS='DIRECT',
1 RECL=117)
Là, on a ouvert un fichier binaire (form=unformatted) existant (status=old) en accès direct, avec une longeur d'enregistrement de 117 caractères.Pour l'instant, c'est simple (si ce n'est que le code commence en colonne 7 et que la colonne 6 contient un chiffre qui est utilisé par le compilateur comme un caractère de continuation de ligne).
Puis, on lit quelques données
NREC=1
READ(1,REC=NREC)
1 valeur1, valeur2, valeur3, valeur4,
1 ...,
1 valeurN
Pour simplifier, j'ai omis les valeur5, 6, ... jusqu'à N.
Cette liste s'appelle une liste d'entrée-sortie. Elle peut contenir autant de valeur que souhaité par le programmeur. Une seule de ces liste peut donc être utilisée pour lire tout le contenu d'un fichier. Jusque là, pas de problème particulier.
La où ça se gate, c'est lorsque cette liste est augmentée d'une liste d'entrée-sortie avec boucle implicite :
INTEGER a(10)
INTEGER b(10)
INTEGER c(10)
NREC=1
READ(1,REC=NREC)
1 valeur1, valeur2, valeur3, valeur4,
1 (a(k), b(k), c(k), k=1,10)
Cette instruction est équivalente a (pseudo-code) :
READ(1, REC=NREC) valeur1, valeur2, valeur3, valeur4,
for (k=1; k<=10; ++k) {
READ(1, REC=NREC) a(k), b(k), c(k)
}
Et voilà le coupable qui se profile au loin :
INTEGER a(10)
INTEGER b(10)
INTEGER c(10)
NREC=1
READ(1,REC=NREC)
1 NB_OBJ,
1 (a(k), b(k), c(k), k=1,NB_OBJ)
Si ce code peut sembler innocent, il n'en est rien : NB_OBJ est peut être supérieur a 10 dans le fichier, auquel cas ce code va systématiquement provoquer une erreur sévère au moment de l'exécution.
Au niveau de la structure, que voit-on ? Il est impossible de tester la valeur de NB_OBJ avant de lire les données dans les tableaux a,b et c. Conséquemment, il est impossible de vérifier le fonctionnement de cette ligne de code sans tester. Et le test dépends très fortement des conditions d'entrée : si les fichiers de test sont mal choisi, le code peut sembler fonctionner.
Ce qui, au final, nous amène à une conclusion : à faire l'économie de l'écriture, on ramasse souvent des problèmes qui ne devraient même pas exister. Et pendant qu'on y est, prions pour que le Fortran 77 ne continue pas à détruire le moral des ingénieurs dans le monde entier.
Commentaires
Aucun commentaire pour le moment.
:: Fil rss des commentaires de ce billet ::
Ajouter un commentaire