La gestion des fichiers en COBOL paraît simple au premier abord. On déclare un fichier dans la division ENVIRONMENT, on décrit sa structure d'enregistrement dans la division DATA, et on utilise les instructions OPEN, READ ou WRITE, et CLOSE dans la division PROCEDURE. Quatre verbes, un cycle de vie. Le problème, c'est que les programmes COBOL restent rarement simples : au fil des décennies de maintenance, ils accumulent logique, gestion des exceptions, branchements conditionnels et appels PERFORM. Ce qui commence comme un modèle simple d'ouverture et de fermeture uniques se transforme insidieusement en quelque chose de plus complexe : des fichiers ouverts deux fois dans un même chemin d'exécution, des instructions CLOSE exécutées alors qu'aucun fichier n'est ouvert, des sorties d'erreur qui s'écartent complètement de l'instruction CLOSE.
Aucun de ces problèmes n'est immédiatement visible. Le programme compile. Il s'exécute souvent sans erreur avec les entrées testées. Il échoue silencieusement avec des combinaisons d'entrées imprévues, ou dégrade les performances de la fenêtre de traitement par lots si progressivement que personne ne fait le lien de cause à effet. L'analyse statique les détecte avant même que cela ne se produise.
Détection des fuites dans toutes les langues
SMART TS XL cartographie les chaînes de références à longue durée de vie et les structures de données illimitées sur l'ensemble de votre code source.
En savoir plusLes quatre défauts d'état de fichier qu'il convient de détecter
Avant d'aborder les mécanismes de détection, voici une classification claire de ce que vous recherchez. Tous les problèmes liés aux fichiers COBOL ne sont pas identiques.
| Défaut | Que se passe-t-il lors de l'exécution ? | Gravité |
|---|---|---|
| Double OUVERT | OUVRIR un fichier déjà ouvert → STATUT DU FICHIER 41 ou erreur d'exécution | Haute |
| FERMER sans ouverture préalable | FERMER un fichier qui n'a jamais été ouvert → STATUT DU FICHIER 42 ou erreur d'ouverture | Haute |
| Fermeture manquante sur la sortie normale | Fichier laissé ouvert lors de l'arrêt de l'exécution → Le système d'exploitation le ferme, mais les tampons non vidés présentent un risque de perte de données. | Moyenne |
| Fermeture manquante en cas d'erreur de sortie | Le programme s'arrête anormalement avec un fichier ouvert → corruption potentielle des enregistrements dans les fichiers VSAM | Haute |
| Opérations OPEN/CLOSE redondantes en boucle | Ouverture et fermeture du fichier à chaque itération → surcharge d'E/S importante | Moyen-élevé |
Point clé : Les défauts les plus critiques, à savoir les doubles ouvertures et fermetures sans ouverture, entraînent des défaillances d’exécution immédiates ou des risques pour l’intégrité des données. Les défauts de performance (ouvertures/fermetures au niveau des boucles) ne génèrent aucune erreur, mais seulement des ralentissements des traitements par lots dont la cause reste inconnue.
Ce qui rend cela difficile à trouver manuellement
Le problème n'est pas d'identifier le schéma. Tout développeur sait qu'il ne faut pas ouvrir un fichier deux fois. Le problème, c'est que le flux de contrôle COBOL est non linéaire, ce qui rend le traçage manuel peu fiable.
Prenons l'exemple d'un programme ayant cette structure :
Cobol
PROCEDURE DIVISION.
MAIN-LOGIC.
PERFORM INITIALIZATION
PERFORM PROCESS-RECORDS
PERFORM TERMINATION
STOP RUN.
INITIALIZATION.
OPEN INPUT CUSTOMER-FILE
OPEN OUTPUT REPORT-FILE
MOVE 0 TO WS-ERROR-FLAG.
PROCESS-RECORDS.
READ CUSTOMER-FILE INTO WS-CUSTOMER-REC
AT END MOVE 1 TO WS-EOF-FLAG
END-READ
IF WS-ERROR-FLAG = 1
PERFORM ERROR-EXIT
END-IF
PERFORM UNTIL WS-EOF-FLAG = 1
PERFORM PROCESS-ONE-RECORD
READ CUSTOMER-FILE INTO WS-CUSTOMER-REC
AT END MOVE 1 TO WS-EOF-FLAG
END-EXEC
END-PERFORM.
ERROR-EXIT.
DISPLAY 'Error in processing'
CLOSE CUSTOMER-FILE *> CLOSE here...
STOP RUN.
TERMINATION.
CLOSE CUSTOMER-FILE *> ...and CLOSE here too
CLOSE REPORT-FILE
STOP RUN.
Pouvez-vous repérer le défaut sans analyser chaque chemin d'exécution ? WS-ERROR-FLAG est fixé à 1 à l'intérieur PROCESS-ONE-RECORD (peut-être par un sous-programme appelé), le contrôle est transmis à ERROR-EXITce qui ferme le fichier et s'arrête. C'est exact. Mais si WS-ERROR-FLAG is pas L'ensemble est défini, la boucle est terminée, PROCESS-RECORDS retours, et TERMINATION courses, ce qui ferme également CUSTOMER-FILEDeux fermetures, une ouverture. Durée d'exécution : 42.
Il s'agit d'un programme simple en trois sections. Les programmes réels comportent vingt sections, des appels conditionnels à PERFORM, des instructions GO TO dans du code hérité et des routines de gestion des exceptions qui appellent elles-mêmes d'autres routines. Le traçage manuel est non seulement source d'erreurs, mais aussi impossible à gérer.
Comment les modèles d'analyse statique enregistrent l'état des fichiers
L'analyse statique détecte ces défauts en construisant un graphe de flux de contrôle du programme et en propageant l'état du fichier le long de chaque chemin.
L'analyse attribue à chaque fichier une variable d'état avec trois valeurs possibles :
CLOSEDLe fichier n'a pas été ouvert ou a été fermé avec succès.OPENLe fichier a été ouvert mais pas encore fermé.UNKNOWN, l'état ne peut pas être déterminé statiquement (par exemple, ouverture conditionnelle dans une branche non entièrement analysée)
À chaque instruction OPEN, l'analyse vérifie : ce fichier est-il déjà dans l'état OPEN? Si oui → défaut double OUVERT.
À chaque instruction CLOSE : ce fichier est-il dans l'état CLOSED or UNKNOWN? Si FERMÉ → fermer sans défaut ouvert.
À chaque étape de l'arrêt ou de la sortie du programme : un fichier est-il encore dans cet état ? OPEN? Si oui → défaut de fermeture manquant.
Pour les boucles, l'analyse vérifie si une instruction OPEN ou CLOSE est dominée par un en-tête de boucle, ce qui signifie qu'elle exécute chaque itération.
Fais attention: Les cas les plus difficiles pour tout analyseur sont les appels PERFORM dans des routines partagées.
ERROR-HANDLERLa fonction PERFORM est appelée depuis douze endroits différents dans un programme. L'état du fichier au moment de l'appel PERFORM détermine si la fermeture interne doit être effectuée.ERROR-HANDLERest correct ou erroné. Un analyseur qui ne propage pas l'état à travers les chaînes PERFORM produira des faux négatifs (manquant de véritables défauts) ou des faux positifs (signalant du code correct).
L'ouverture/fermeture au niveau de la boucle : un défaut de performance sans code d'erreur
Ce modèle ne génère aucune erreur d'exécution ni aucune anomalie de statut de fichier. Il s'exécute simplement lentement, potentiellement plusieurs ordres de grandeur plus lentement que nécessaire.
Cobol
*> PROBLEMATIC: file opened and closed on every iteration
PROCESS-ALL-REGIONS.
PERFORM VARYING WS-REGION-ID FROM 1 BY 1
UNTIL WS-REGION-ID > 10
OPEN INPUT CUSTOMER-FILE
PERFORM PROCESS-REGION-RECORDS
CLOSE CUSTOMER-FILE
END-PERFORM.
À moins que le fichier ne soit physiquement partitionné par région, cette approche engendre une surcharge inutile. En pratique, il serait préférable d'ouvrir le fichier une seule fois, de lire tous les enregistrements et d'appliquer le filtrage en mémoire ou par un mécanisme logique.
Chaque ouverture d'un fichier VSAM implique une recherche dans le catalogue, l'initialisation de l'ACB et l'allocation d'un pool de mémoires tampons. Chaque fermeture vide les mémoires tampons, met à jour le catalogue et libère l'ACB. Pour un fichier comportant dix régions, ce processus se répète dix fois au lieu d'une seule. Pour un fichier contenant 10 000 enregistrements et mille régions, le calcul devient complexe.
Cobol
*> CORRECT: open once, filter inside the loop
PROCESS-ALL-REGIONS.
OPEN INPUT CUSTOMER-FILE
PERFORM VARYING WS-REGION-ID FROM 1 BY 1
UNTIL WS-REGION-ID > 10
PERFORM PROCESS-REGION-RECORDS
END-PERFORM
CLOSE CUSTOMER-FILE.
L'analyse statique détecte ce problème en identifiant les instructions OPEN et CLOSE qui sont dominées par les boucles, c'est-à-dire que chaque exécution du corps de la boucle déclenche l'appel à OPEN ou à CLOSE. Cette détection nécessite que le graphe de flux de contrôle représente la structure de la boucle, et non seulement la séquence des instructions.
ÉTAT DU FICHIER : Signal d’état du fichier de votre programme, si vous le vérifiez
Chaque opération sur un fichier COBOL modifie le champ FILE STATUS défini dans l'entrée FILE-CONTROL. Un programme qui vérifie FILE STATUS après chaque opération OPEN, READ, WRITE et CLOSE peut détecter et corriger toute anomalie d'état de fichier lors de son exécution. Un programme qui ignore FILE STATUS navigue à vue.
Liste de vérification : Codes d’état de fichier que tout développeur COBOL devrait connaître
00, Réussite10Fin du fichier (LECTURE : plus d’enregistrements)35Fichier introuvable (OPEN INPUT : le fichier n'existe pas)41Fichier déjà ouvert (OUVERT sur un fichier à l'état OUVERT)42Fichier non ouvert (FERMER ou LIRE sur un fichier à l'état FERMÉ)47Tentative de lecture sur un fichier non ouvert (entrée ou E/S)48, écriture tentée sur un fichier non ouvert OUTPUT, IO ou EXTEND97Fichier ouvert avec succès (spécifique à IBM, certains environnements)
Cobol
FILE-CONTROL.
SELECT CUSTOMER-FILE
ASSIGN TO CUSTFILE
FILE STATUS IS WS-CUST-FILE-STATUS.
WORKING-STORAGE SECTION.
01 WS-CUST-FILE-STATUS PIC XX.
PROCEDURE DIVISION.
OPEN INPUT CUSTOMER-FILE
IF WS-CUST-FILE-STATUS NOT = '00'
DISPLAY 'OPEN failed: ' WS-CUST-FILE-STATUS
PERFORM ABEND-ROUTINE
END-IF.
Fais attention: Une erreur de maintenance courante consiste à déclarer FILE STATUS dans l'entrée FILE-CONTROL sans jamais y faire référence.
WS-CUST-FILE-STATUSDans la division PROCEDURE, le champ est renseigné après chaque opération sur les fichiers. Toutefois, si aucun code ne le vérifie, le programme ignore les erreurs. L'analyse statique peut révéler ce comportement : le champ FILE STATUS est déclaré mais jamais utilisé dans la logique conditionnelle.
Trois exemples concrets de code COBOL à l'origine de défauts
Modèle 1 : Le problème de sortie d'erreur partagé
Un programme comporte plusieurs sections de traitement, chacune dotée de son propre gestionnaire d'erreurs. Plusieurs gestionnaires d'erreurs ferment le fichier avant de retourner. La routine de terminaison normale ferme également le fichier. Si une erreur survient et que la récupération se poursuit au-delà du gestionnaire d'erreurs, le fichier est fermé deux fois.
Cobol
VALIDATE-RECORDS.
READ CUSTOMER-FILE INTO WS-REC
AT END MOVE 1 TO WS-EOF
END-READ
IF WS-CUST-FILE-STATUS NOT = '00' AND '10'
CLOSE CUSTOMER-FILE *> closes here on read error
PERFORM WRITE-ERROR-LOG
GO TO TERMINATION *> skips to close in TERMINATION?
END-IF.
TERMINATION.
CLOSE CUSTOMER-FILE *> double close if GO TO reached here
CLOSE REPORT-FILE
STOP RUN.
Le GO TO TERMINATION transfère le contrôle directement dans TERMINATION, qui exécute ses propres CLOSE CUSTOMER-FILE. ÉTAT DU FICHIER 42.
Solution : Utiliser une routine de fermeture centralisée unique. Chaque chemin de sortie appelle la même routine, qui vérifie si le fichier est ouvert avant de le fermer.
Modèle 2 : L’OUVERTURE conditionnelle
L'ouverture d'un fichier est conditionnelle et ne se produit que lorsqu'un certain mode de traitement est actif. En revanche, la fermeture est inconditionnelle et intervient dans tous les cas, même lorsque le fichier n'a jamais été ouvert.
Cobol
INITIALIZATION.
IF WS-PROCESSING-MODE = 'FULL'
OPEN OUTPUT AUDIT-FILE *> only opened in FULL mode
END-IF.
TERMINATION.
CLOSE AUDIT-FILE *> ALWAYS closes -- FILE STATUS 42 in PARTIAL mode
STOP RUN.
Ce défaut est invisible lors des tests si ceux-ci sont toujours exécutés en mode COMPLET. Il apparaît en production dès la première exécution en mode PARTIEL.
Modèle 3 : EXÉCUTER à travers les unités de compilation
Dans les programmes qui utilisent CALL pour appeler des sous-programmes, un fichier ouvert dans le programme principal peut être transmis à un sous-programme qui le ferme, puis le programme principal le ferme à nouveau.
Cobol
*> Main program
CALL 'SUBPROG1' USING CUSTOMER-FILE-STATUS
*> SUBPROG1 closes CUSTOMER-FILE internally
CLOSE CUSTOMER-FILE *> double close
Ce modèle nécessite une analyse interprocédurale , traçant l'état du fichier à travers la limite CALL jusqu'au comportement du sous-programme, ce qu'une simple analyse intra-programme ne peut pas détecter.
Ce dont un analyseur statique a besoin pour bien faire cela
Tous les outils d'analyse statique ne gèrent pas l'analyse de l'état des fichiers COBOL avec la même profondeur. Voici une liste de critères pour évaluer leurs capacités :
L'outil prend-il en charge les chaînes PERFORM ? Les programmes COBOL utilisent PERFORM pour appeler des paragraphes et des sections nommés. Les opérations sur les fichiers effectuées à l'intérieur d'une cible PERFORM doivent être visibles par le système de suivi d'état de l'appelant.
L'outil gère-t-il les instructions PERFORM VARYING en ligne (boucles) ? La détection de boucles est nécessaire pour identifier les opérations OPEN/CLOSE dominées par les boucles.
Est-ce que le suivi de l'état est possible lors des instructions GO TO ? Les programmes COBOL anciens utilisent abondamment les instructions GO TO. Un analyseur incapable de suivre les arêtes GO TO dans le graphe de flux de contrôle passera à côté de catégories entières de défauts.
Gère-t-il les opérations COPY et REPLACE ? Le code de gestion des fichiers se trouve souvent dans les membres COPY. Un analyseur qui n'étend pas les membres COPY avant l'analyse manquera des opérations définies dans le code inclus.
Vérifie-t-il l'utilisation de FILE STATUS ? Une analyse complète vérifie non seulement si FILE STATUS est déclaré, mais aussi s'il est effectivement vérifié après chaque opération.
Effectue-t-il une analyse interprocédurale ? Les sous-programmes appelés qui effectuent des opérations sur les fichiers créent des dépendances d'état entre programmes. Une couverture complète nécessite de suivre les chaînes d'appels.
Point clé : Un outil qui ne vérifie qu’un seul paragraphe ou une seule section passera à côté de la plupart des défauts réels. Les défauts critiques en production, ceux qui ont mis des années à apparaître et des heures à diagnostiquer, sont ceux qui s’étendent sur plusieurs sections, des branches conditionnelles et des routines appelées.
Que faire des résultats : un cadre de priorisation
Lorsqu'une analyse statique révèle des défauts dans les fichiers, tous les résultats ne se valent pas. Voici comment les hiérarchiser :
Corrigez immédiatement (avant le prochain traitement par lots) :
- Double OUVRIR dans tout chemin d'exécution où le STATUT DE FICHIER 41 provoquerait un arrêt anormal
- FERMER sans OUVRIR dans les chemins qui s'exécutent en production
- Absence de la commande CLOSE sur les chemins de sortie d'erreur pour les fichiers VSAM (risque d'intégrité d'écriture)
Calendrier du prochain sprint :
- Opérations d'ouverture/fermeture dominées par les boucles avec un impact mesurable sur la fenêtre de traitement par lots
- Absence de vérifications de l'état des fichiers critiques (audit, transaction, rapport)
- OUVERTURE conditionnelle avec FERMETURE inconditionnelle dans les programmes multimodes
Suivi et traitement lors de la prochaine phase de modernisation :
- Déclarations d'état de fichier manquantes
- FERMER uniquement sur les chemins de sortie normaux (le système d'exploitation le gère, mais c'est une mauvaise pratique)
- Défauts interprocéduraux où la correction nécessite la coordination de modifications entre plusieurs programmes
Comment SMART TS XL Analyse l'état des fichiers COBOL
SMART TS XL's analyse de code statique Ce modèle construit le flux de contrôle de chaque programme COBOL de l'environnement, en développant les membres COPY, en suivant les chaînes PERFORM, en traçant les instructions GO TO et en propageant l'état des fichiers à travers chaque branche de chaque instruction conditionnelle. Il ne s'agit pas d'une analyse par correspondance de motifs ; c'est un modèle structurel de ce que fait réellement le programme à chaque point accessible de son exécution.
La fonctionnalité de cartographie des dépendances applicatives étend cette capacité à la dimension interprocédurale : lorsqu’un programme COBOL appelle un sous-programme effectuant des opérations sur des fichiers, la cartographie des dépendances représente cette relation, permettant ainsi une analyse qui dépasse les limites des unités de compilation. Les défauts de double ouverture (Double OPEN) qui s’étendent sur un programme principal et un sous-programme appelé sont visibles dans le modèle structurel, contrairement à toute analyse intra-programme.
La fonction de recherche d'entreprise permet d'exploiter les résultats à grande échelle : elle permet de trouver en quelques secondes, parmi des millions de lignes de COBOL, tous les programmes du portefeuille qui ouvrent un ensemble de données spécifique, tous les membres COPY contenant une instruction CLOSE, tous les programmes dont la cible PERFORM contient une instruction OPEN. Pour une équipe de modernisation préparant la migration d'une charge de travail par lots vers le cloud, cette fonction transforme un audit manuel de plusieurs semaines en une requête ciblée.
La fonctionnalité d'extension JCL ajoute le contexte opérationnel : les étapes de travail JCL qui appellent chaque programme, les fichiers référencés par chaque instruction DD et la manière dont la gestion des fichiers dans le code COBOL est liée aux fichiers physiques définis dans le JCL. Un défaut de type « FERMÉ » sur un fichier défini par le JCL comme fichier de sortie critique est prioritaire par rapport au même défaut sur un fichier de travail temporaire, et cette priorisation nécessite de connaître le contexte JCL de chaque programme COBOL.
Leçon plus générale : l’état des fichiers n’est qu’une dimension.
Les opérations redondantes sur les fichiers sont un cas particulier d'un problème plus général : les programmes COBOL qui ont évolué au fil des décennies contiennent des comportements dépendants de l'état (état des fichiers, états des commutateurs, états des compteurs) qui ne peuvent être correctement compris qu'en traçant chaque chemin d'exécution possible à travers le graphe de flux de contrôle complet.
L'analyse humaine de ce type de code est lente, incomplète et incohérente. Différents développeurs découvrent des défauts différents. Un même développeur, en relisant le même programme à deux reprises, peut trouver des défauts différents. L'analyse statique est systématique : elle applique les mêmes règles à chaque chemin d'accès dans chaque programme, systématiquement, sans fatigue ni supposition.
Pour les équipes gérant d'importants portefeuilles COBOL, que ce soit pour la maintenance courante, la modernisation de systèmes existants ou les audits de conformité, l'intérêt d'une analyse systématique de l'état des fichiers ne se limite pas à la détection des défauts. Il réside surtout dans la certitude que le portefeuille a été analysé de manière exhaustive et que les défauts restants sont identifiés plutôt que dissimulés.


