Registrer åbninger og lukninger af redundante filer i COBOL

Sådan registrerer du åbninger og lukninger af redundante filer i COBOL: En statisk analysemetode

Filhåndtering i COBOL er på overfladen bedragerisk simpel. Du deklarerer en fil i ENVIRONMENT DIVISION, beskriver dens recordlayout i DATA DIVISION og bruger OPEN, READ eller WRITE og CLOSE i PROCEDURE DIVISION. Fire verber, én livscyklus. Problemet er, at COBOL-programmer sjældent forbliver simple, de akkumulerer logik, undtagelsesstier, betingede forgreninger og PERFORM-kald over årtiers vedligeholdelse. Det, der starter som et rent enkelt-åbne, enkelt-lukke-mønster, muterer stille og roligt til noget mere komplekst: filer åbnet to gange i en enkelt udførelsessti, CLOSE-sætninger, der kører, når ingen filer er åbne, og fejlen afslutter den forgrening helt efter CLOSE.

Ingen af ​​disse problemer er umiddelbart synlige. Programmet kompilerer. Det kører ofte uden fejl på de input, du tester. Det fejler lydløst på inputkombinationer, du aldrig har forventet, eller forringer batchvinduets ydeevne så gradvist, at ingen forbinder årsag til virkning. Statisk analyse finder dem, før noget af det sker.

Lækagedetektion på tværs af alle sprog

SMART TS XL kortlægger langlivede referencekæder og ubegrænsede datastrukturer på tværs af hele din kodebase.

Mere info

De fire filtilstandsfejl, der er værd at finde

Før vi går i dybden med detektionsmekanik, er her en klar taksonomi over, hvad du leder efter. Ikke alle COBOL-filproblemer er skabt lige.

DefektHvad sker der under kørselSeverity
Dobbelt ÅBENÅBN på en allerede åben fil → FILSTATUS 41 eller afbrydHøj
LUK uden forudgående ÅBENLUK på en fil, der aldrig blev åbnet → FILSTATUS 42 eller abendHøj
Mangler LUK ved normal udgangFilen forbliver åben ved STOP RUN → OS lukker den, men ikke-tømte buffere risikerer datatabMedium
Manglende LUK ved fejlafslutningProgrammet afbryder funktionen med åben fil → potentiel postkorruption på VSAM-filerHøj
Redundant ÅBEN/LUKKET i en løkkeFil åbnes og lukkes ved hver iteration → alvorlig I/O-overheadMedium-Høj

Vigtig konklusion: De mest alvorlige fejl, dobbelt ÅBEN og LUK uden ÅBEN, producerer øjeblikkelige fejl under kørsel eller dataintegritetsrisici. Ydelsesfejlene (åbn/luk på loop-niveau) producerer slet ingen fejl, kun langsomme batchjob, som ingen har sporet til årsagen.

Hvad gør dette svært at finde manuelt

Udfordringen er ikke at identificere mønsteret. Enhver udvikler ved, at man ikke bør åbne en fil to gange. Udfordringen er, at COBOL-kontrolflowet er ikke-lineært på måder, der gør manuel sporing upålidelig.

Overvej et program med denne struktur:

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.

Kan du finde fejlen uden at spore alle udførelsesstier? WS-ERROR-FLAG er sat til 1 indeni PROCESS-ONE-RECORD (måske af et kaldt underprogram), styres der til ERROR-EXIT, hvilket lukker filen og stopper. Det er korrekt. Men hvis WS-ERROR-FLAG is ikke sæt, løkken fuldføres, PROCESS-RECORDS returneringer, og TERMINATION kører, som også lukker CUSTOMER-FILETo lukninger, én åbning. FILSTATUS UNDER KØRING 42.

Dette er et simpelt program med tre sektioner. Rigtige programmer har tyve sektioner, betingede PERFORM-kald, GOTO-sætninger i ældre kode og rutiner til håndtering af undtagelser, der selv kalder andre rutiner. Manuel sporing er ikke bare fejlbehæftet, den er ikke håndterbar.


Hvordan statisk analyse modellerer filtilstand

Statisk analyse registrerer disse defekter ved at konstruere en kontrolflowgraf for programmet og udbrede filtilstanden langs hver sti.

Analysen tildeler hver fil en tilstandsvariabel med tre mulige værdier:

  • CLOSED, filen er ikke blevet åbnet, eller den blev lukket
  • OPEN, filen er blevet åbnet og endnu ikke lukket
  • UNKNOWN, tilstanden kan ikke bestemmes statisk (f.eks. betinget åbning i en gren, der ikke er fuldt analyseret)

Ved hver OPEN-sætning kontrollerer analysen: er denne fil allerede i tilstanden OPENHvis ja → dobbelt ÅBEN-defekt.

Ved hver CLOSE-sætning: er denne fil i tilstand CLOSED or UNKNOWNHvis LUKKET → luk uden åben defekt.

Ved hver sti til STOP KØR eller AFSLUT PROGRAM: er nogen fil stadig i tilstanden OPENHvis ja → manglende luk defekt.

For løkker kontrollerer analysen, om en OPEN- eller CLOSE-sætning domineres af en løkkeheader, hvilket betyder, at den udfører hver iteration.

Pas på: De sværeste tilfælde for enhver analysator er PERFORM-kald til delte rutiner. Hvis ERROR-HANDLER kaldes fra tolv forskellige steder i et program, bestemmer filtilstanden på PERFORM-kaldets tidspunkt, om lukning indenfor ERROR-HANDLER er korrekt eller fejlagtig. En analysator, der ikke udbreder tilstand gennem PERFORM-kæder, vil producere falske negative resultater (manglende reelle defekter) eller falske positive resultater (markering af korrekt kode).


Loop-niveau ÅBEN/LUKKET: En ydeevnefejl uden fejlkode

Dette mønster producerer ingen runtime-fejl og ingen FILE STATUS-anomali. Det kører simpelthen langsomt, potentielt flere størrelsesordener langsommere end nødvendigt.

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.

Medmindre filen er fysisk partitioneret efter region, forårsager denne fremgangsmåde unødvendig overhead. I praksis ville det være bedre at åbne filen én gang, læse alle poster og anvende filtrering i hukommelsen eller via logik.

Hver ÅBEN-handling på en VSAM-fil involverer et katalogopslag, ACB-initialisering og bufferpuljeallokering. Hver LUK tømmer buffere, opdaterer kataloget og frigiver ACB'en. For en fil med ti regioner sker dette ti gange i stedet for én gang. For en fil med 10,000 poster og tusind regioner bliver matematikken smertefuld.

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.

Statisk analyse registrerer dette ved at identificere OPEN- og CLOSE-sætninger, der er loop-dominerede, dvs. at hver udførelse af loop-kroppen udfører OPEN eller CLOSE. Detektionen kræver, at kontrolflowgrafen repræsenterer loopstrukturen, ikke kun sætningssekvensen.


FILSTATUS: Dit programs filtilstandssignal, hvis du markerer det

Hver COBOL-filoperation angiver feltet FILE STATUS, som er defineret i FILE-CONTROL-posten. Et program, der kontrollerer FILE STATUS efter hver OPEN, READ, WRITE og CLOSE, kan registrere og reagere på enhver filtilstandsanomali under kørsel. Et program, der ignorerer FILE STATUS, flyver i blinde.

Tjekliste: FILSTATUS-koder, som alle COBOL-udviklere bør kende

  • 00, Vellykket gennemførelse
  • 10, Slut på fil (LÆS: ingen flere poster)
  • 35, Fil ikke fundet (ÅBN INPUT: filen findes ikke)
  • 41, Filen er allerede åben (ÅBEN på en fil i ÅBEN tilstand)
  • 42, Filen er ikke åben (LUK eller LÆS på en fil i LUKKET tilstand)
  • 47, LÆSNING forsøgt på fil ikke åbnet INPUT eller IO
  • 48, SKRIVNING forsøgt på fil ikke åbnet OUTPUT, IO eller EXTEND
  • 97, Fil åbnet (IBM-specifik, nogle miljøer)

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.

Pas på: En almindelig vedligeholdelsesfejl er at deklarere FILE STATUS i FILE-CONTROL-posten, men aldrig referere til den. WS-CUST-FILE-STATUS i PROCEDURE-AFDELINGEN. Feltet udfyldes efter hver filhandling, men hvis ingen kode kontrollerer det, kører programmet forbi fejl lydløst. Statisk analyse kan markere dette mønster: FILSTATUS erklæret, men aldrig refereret til i betinget logik.


Tre COBOL-mønstre fra den virkelige verden, der forårsager defekter

Mønster 1: Det delte fejl-afslutningsproblem

Et program har flere behandlingssektioner, hver med sin egen fejlbehandler. Flere fejlbehandlere lukker filen, før de returnerer. Den normale afslutningsrutine lukker også filen. Hvis der opstår en fejl, og gendannelsen fortsætter forbi fejlbehandleren, lukkes filen to gange.

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.

GO TO TERMINATION overfører kontrollen direkte til TERMINATION, som udfører sin egen CLOSE CUSTOMER-FILE. FILSTATUS 42.

Rettelse: Brug en enkelt centraliseret lukkerutine. Hver exit-sti kalder den samme rutine, som kontrollerer, om filen er åben, før den lukkes.

Mønster 2: Den betingede ÅBEN

En fil åbnes betinget, kun når en bestemt behandlingstilstand er aktiv. Men LUKNINGEN er ubetinget og forekommer i alle udførelsesstier, inklusive dem hvor filen aldrig blev åbnet.

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.

Denne fejl er usynlig i test, hvis testene altid kører i FULD tilstand. Den dukker op i produktionen ved den første kørsel i DELVIS tilstand.

Mønster 3: PERFORM på tværs af kompileringsenheder

I programmer, der bruger CALL til at kalde underprogrammer, kan en fil, der er åbnet i hovedprogrammet, sendes til et underprogram, der lukker den, hvorefter hovedprogrammet lukker den igen.

COBOL

      *> Main program
       CALL 'SUBPROG1' USING CUSTOMER-FILE-STATUS
       *> SUBPROG1 closes CUSTOMER-FILE internally
       CLOSE CUSTOMER-FILE    *> double close

Dette mønster kræver interprocedurel analyse , hvor filtilstanden spores på tværs af CALL-grænsen ind i underprogrammets adfærd, hvilket simpel intraprogramanalyse ikke kan opdage.


Hvad en statisk analysator skal bruge for at gøre dette godt

Ikke alle statiske analyseværktøjer håndterer COBOL-filtilstandsanalyse med samme dybde. Her er en beslutningstjekliste til evaluering af kapacitet:

Håndterer værktøjet PERFORM-kæder? COBOL-programmer bruger PERFORM til at kalde navngivne afsnit og sektioner. Filhandlinger i et PERFORM-mål skal være synlige for den kaldendes tilstandssporing.

Håndterer værktøjet inline PERFORM VARYING (loops)? Loopdetektion er nødvendig for at identificere loopdominerede OPEN/CLOSE-operationer.

Sporer den tilstand på tværs af GO TO? Ældre COBOL-programmer bruger GO TO i vid udstrækning. En analysator, der ikke kan følge GO TO-kanter i kontrolflowgrafen, vil overse hele klasser af defekter.

Håndterer den COPY og REPLACE? Filhåndteringskode findes ofte i COPY-medlemmer. En analysator, der ikke udvider COPY-medlemmer før analyse, vil overse operationer defineret i den inkluderede kode.

Kontrollerer den brugen af ​​FILE STATUS? En komplet analyse kontrollerer ikke blot, om FILE STATUS er deklareret, men også om den rent faktisk kontrolleres efter hver handling.

Udfører den interprocedurel analyse? Kaldede underprogrammer, der udfører filoperationer, skaber tilstandsafhængigheder på tværs af programmer. Sand dækning kræver følgende kaldkæder.

Vigtig konklusion: Et værktøj, der kun kontrollerer inden for et enkelt afsnit eller afsnit, vil overse de fleste fejl i den virkelige verden. De fejl, der er vigtige i produktionen, dem der tog år at opstå og timer at diagnosticere, er dem, der spænder over flere sektioner, betingede forgreninger og kaldet rutiner.


Hvad skal man gøre med resultaterne: En prioriteringsramme

Når statisk analyse afslører filfejl, er ikke alle fund ens. Sådan sorterer du dem:

Ret straks (før næste batchkørsel):

  • Dobbelt ÅBN i enhver udførelsessti, hvor FILSTATUS 41 ville forårsage en fejl
  • LUK uden ÅBEN i stier, der udføres i produktion
  • Manglende LUK på fejludgangsstier for VSAM-filer (risiko for skriveintegritet)

Tidsplan for næste sprint:

  • Loop-domineret ÅBEN/LUKKE med målbar effekt af batchvinduet
  • Manglende FILSTATUS-kontroller på kritiske filer (revision, transaktion, rapport)
  • Betinget ÅBEN med ubetinget LUKNING i multimode-programmer

Spor og adresse under næste moderniseringspas:

  • Manglende FILSTATUS-deklarationer
  • LUK kun på normale udgangsstier (OS håndterer det, men dårlig praksis)
  • Interproceduremæssige defekter, hvor rettelsen kræver koordinering af ændringer på tværs af flere programmer

Hvordan SMART TS XL Analyserer COBOL-filens tilstand

SMART TS XL's statisk kodeanalyse bygger en kontrolflowmodel for hvert COBOL-program i miljøet, udvider COPY-medlemmer, følger PERFORM-kæder, sporer GO TO-kanter og udbreder filtilstand gennem hver gren af ​​hver betinget funktion. Det er ikke en mønstermatchningsscanning; det er en strukturel model af, hvad programmet rent faktisk gør på hvert tilgængeligt punkt i sin udførelse.

Funktionen til applikationsafhængighedskortlægning udvider dette til den interprocedurelle dimension: når et COBOL-program kalder et underprogram, der udfører filoperationer, repræsenterer afhængighedskortet dette forhold, hvilket muliggør analyse, der krydser grænserne for kompileringsenheder. Dobbelte OPEN-defekter, der spænder over et hovedprogram og et kaldt underprogram, er synlige i den strukturelle model på en måde, de ikke er i nogen intraprogramanalyse.

Virksomhedssøgningsfunktionen gør resultaterne brugbare i stor skala: find alle programmer i porteføljen, der åbner et specifikt datasæt, alle COPY-medlemmer , der indeholder en CLOSE-sætning, alle programmer, der har et PERFORM-mål, der indeholder en OPEN, på tværs af millioner af COBOL-linjer på få sekunder. For et moderniseringsteam, der forbereder sig på at migrere en batch-arbejdsbelastning til skyen, forvandler denne søgefunktion en ugelang manuel revision til en målrettet forespørgsel.

JCL -udvidelsesfunktionen tilføjer den operationelle kontekst: hvilke JCL-jobtrin kalder hvert program, hvilke datasæt hver DD-sætning refererer til, og hvordan filhåndteringen i COBOL-koden forbinder til de fysiske datasæt, der er defineret i JCL. En CLOSE-fejl på en fil, som JCL definerer som et kritisk outputdatasæt, har højere prioritet end den samme fejl på en midlertidig arbejdsfil, og den prioritering kræver kendskab til JCL-konteksten for hvert COBOL-program.


Den bredere lektie: Filtilstand er kun én dimension

Redundante filoperationer er et specifikt eksempel på et mere generelt problem: COBOL-programmer, der har udviklet sig over årtier, indeholder tilstandsafhængige adfærdsmønstre, filtilstande, switchtilstande og tællertilstande, der kun forstås korrekt ved at spore alle mulige udførelsesstier gennem den fulde kontrolflowgraf.

Menneskelig gennemgang af denne type kode er langsom, ufuldstændig og inkonsekvent. Forskellige udviklere finder forskellige fejl. Den samme udvikler, der gennemgår det samme program to gange, finder forskellige fejl. Statisk analyse er systematisk: den anvender de samme regler på hver sti i hvert program, hver gang, uden træthed eller antagelser.

For teams, der administrerer store COBOL-porteføljer, hvad enten det er til løbende vedligeholdelse, til ældre moderniseringsprogrammer eller til compliance-revisioner, er udbyttet af systematisk filtilstandsanalyse ikke kun de fundne fejl. Det er tilliden til, at porteføljen er blevet analyseret fuldstændigt, og at de fejl, der forbliver, er kendte snarere end skjulte.