Filhantering i COBOL är till synes enkelt. Du deklarerar en fil i ENVIRONMENT DIVISION, beskriver dess postlayout i DATA DIVISION och använder OPEN, READ eller WRITE, och CLOSE i PROCEDURE DIVISION. Fyra verb, en livscykel. Problemet är att COBOL-program sällan förblir enkla, de ackumulerar logik, undantagsvägar, villkorliga grenar och PERFORM-anrop under årtionden av underhåll. Det som börjar som ett rent mönster med en enda öppning och en enda stängning muterar tyst till något mer komplext: filer som öppnas två gånger i en enda exekveringsväg, CLOSE-satser som körs när ingen fil är öppen, felmeddelandet avslutar den grenen helt efter CLOSE.
Inget av dessa problem är omedelbart synliga. Programmet kompilerar. Det körs ofta utan fel på de indata du testar. Det misslyckas tyst på indatakombinationer du aldrig förväntat dig, eller försämrar batchfönstrets prestanda så gradvis att ingen kopplar orsak till verkan. Statisk analys hittar dem innan något av det händer.
Läckagedetektering på alla språk
SMART TS XL mappar långlivade referenskedjor och obegränsade datastrukturer över hela din kodbas.
Mer informationDe fyra filtillståndsfel som är värda att hitta
Innan vi går in på detekteringsmekanik, här är en tydlig taxonomi för vad du letar efter. Alla COBOL-filproblem är inte skapade lika.
| defekt | Vad händer vid körning | Svårighetsgraden |
|---|---|---|
| Dubbel ÖPPEN | ÖPPNA på en redan öppen fil → FILSTATUS 41 eller avbryt | Hög |
| STÄNG utan föregående ÖPPNA | STÄNG på en fil som aldrig öppnades → FILSTATUS 42 eller abend | Hög |
| Saknar STÄNG vid normal utgång | Filen lämnas öppen vid STOP RUN → OS stänger den, men buffertar som inte har tömts riskerar dataförlust | Medium |
| Saknar STÄNG vid felmeddelande | Programmet avbryts med filen öppen → potentiell postkorruption på VSAM-filer | Hög |
| Redundant ÖPPNA/STÄNGA i en loop | Fil öppnas och stängs vid varje iteration → allvarlig I/O-overhead | Medelhög |
Viktig slutsats: De mest allvarliga felen, dubbel ÖPPNA och STÄNGA utan ÖPPNA, orsakar omedelbara fel vid körning eller dataintegritetsrisker. Prestandadefelen (öppna/stänga på loopnivå) producerar inga fel alls, bara långsamma batchjobb som ingen har kunnat spåra till orsaken.
Vad gör detta svårt att hitta manuellt
Utmaningen ligger i att inte identifiera mönstret. Alla utvecklare vet att man inte ska öppna en fil två gånger. Utmaningen är att COBOL-kontrollflödet är icke-linjärt på sätt som gör manuell spårning opålitlig.
Tänk dig ett program med denna 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 upptäcka felet utan att spåra varje exekveringsväg? WS-ERROR-FLAG är satt till 1 inuti PROCESS-ONE-RECORD (kanske av ett anropat delprogram), styrningen går till ERROR-EXIT, vilket stänger filen och stoppar. Det stämmer. Men om WS-ERROR-FLAG is inte inställd, loopen är klar, PROCESS-RECORDS returer, och TERMINATION körningar, som också stänger CUSTOMER-FILETvå stängningar, en öppen. Körtidsfilstatus 42.
Detta är ett enkelt program i tre sektioner. Riktiga program har tjugo sektioner, villkorliga PERFORM-anrop, GOTO-satser i äldre kod och rutiner för undantagshantering som själva anropar andra rutiner. Manuell spårning är inte bara felbenägen, den är inte hanterbar.
Hur statisk analys modellerar filtillstånd
Statisk analys upptäcker dessa defekter genom att konstruera ett kontrollflödesdiagram för programmet och sprida filtillståndet längs varje sökväg.
Analysen tilldelar varje fil en tillståndsvariabel med tre möjliga värden:
CLOSED, filen har inte öppnats, eller så stängdes den utan problemOPEN, filen har öppnats och ännu inte stängtsUNKNOWN, tillståndet kan inte bestämmas statiskt (t.ex. villkorlig öppen i en gren som inte analyserats fullständigt)
Vid varje OPEN-sats kontrollerar analysen: är den här filen redan i tillstånd OPENOm ja → dubbel ÖPPEN-defekt.
Vid varje CLOSE-sats: är den här filen i tillstånd CLOSED or UNKNOWNOm STÄNGD → stäng utan öppen defekt.
Vid varje sökväg till STOP KÖR eller EXIT PROGRAM: finns det fortfarande någon fil i tillståndet OPENOm ja → saknas nära defekt.
För loopar kontrollerar analysen om en OPEN- eller CLOSE-sats domineras av en loop-rubrik, vilket innebär att den exekverar varje iteration.
Se upp: De svåraste fallen för alla analysatorer är PERFORM-anrop till delade rutiner. Om
ERROR-HANDLERanropas från tolv olika platser i ett program, avgör filens tillstånd vid punkten för PERFORM-anropet om stängning inutiERROR-HANDLERär korrekt eller felaktig. En analysator som inte sprider tillstånd genom PERFORM-kedjor kommer att producera falska negativa resultat (saknade verkliga defekter) eller falska positiva resultat (flaggar korrekt kod).
ÖPPNA/STÄNGA på loopnivå: Ett prestandafel utan felkod
Det här mönstret producerar inga körtidsfel och inga fel i FILSTATUS. Det körs helt enkelt långsamt, potentiellt flera storleksordningar långsammare än nödvändigt.
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.
Om inte filen är fysiskt partitionerad efter region orsakar den här metoden onödig overhead. I praktiken vore det bättre att öppna filen en gång, läsa alla poster och tillämpa filtrering i minnet eller via logik.
Varje ÖPPNING på en VSAM-fil involverar en katalogsökning, ACB-initiering och buffertpoolallokering. Varje STÄNGNING tömmer buffertar, uppdaterar katalogen och frigör ACB:n. För en fil med tio regioner händer detta tio gånger istället för en gång. För en fil med 10 000 poster och tusen regioner blir matematiken smärtsam.
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 analys detekterar detta genom att identifiera OPEN- och CLOSE-satser som är loopdominerade, det vill säga att varje exekvering av loopkroppen exekverar OPEN eller CLOSE. Detekteringen kräver att kontrollflödesgrafen representerar loopstrukturen, inte bara satssekvensen.
FILSTATUS: Ditt programs filstatussignal, om du markerar den
Varje COBOL-filoperation ställer in fältet FILE STATUS som definieras i FILE-CONTROL-posten. Ett program som kontrollerar FILE STATUS efter varje OPEN, READ, WRITE och CLOSE kan upptäcka och reagera på varje filtillståndsanomali vid körning. Ett program som ignorerar FILE STATUS flyger i blindo.
Checklista: FILSTATUS-koder som alla COBOL-utvecklare bör känna till
00, Lyckad slutförande10, Slut på fil (LÄS: inga fler poster)35, Filen hittades inte (ÖPPNA INGÅNG: filen finns inte)41, Filen är redan öppen (ÖPPEN på en fil i ÖPPET tillstånd)42, Filen kan inte öppnas (STÄNGD eller LÄST på en fil i STÄNGD tillstånd)47, LÄSNING försökte göras på fil som inte öppnades INPUT eller IO48, SKRIVFÖRSÖKAD på fil som inte öppnades OUTPUT, IO eller EXTEND97, Filen öppnades (IBM-specifik, vissa 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.
Se upp: Ett vanligt underhållsfel är att deklarera FILE STATUS i FILE-CONTROL-posten men aldrig referera till den.
WS-CUST-FILE-STATUSi PROCEDURE DIVISION. Fältet fylls i efter varje filoperation, men om ingen kod kontrollerar det kör programmet fel utan att spela in dem. Statisk analys kan flagga detta mönster: FILE STATUS deklarerad men aldrig refererad i villkorlig logik.
Tre verkliga COBOL-mönster som orsakar defekter
Mönster 1: Det delade fel- och utgångsproblemet
Ett program har flera bearbetningssektioner, var och en med sin egen felhanterare. Flera felhanterare stänger filen innan den återgår. Den normala avslutningsrutinen stänger också filen. Om ett fel uppstår och återställningen fortsätter förbi felhanteraren stängs filen två gånger.
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.
Ocuco-landskapet GO TO TERMINATION överför kontrollen direkt till TERMINATION, som utför sin egen CLOSE CUSTOMER-FILE. FILSTATUS 42.
Åtgärd: Använd en enda centraliserad stängningsrutin. Varje utgångsväg anropar samma rutin, som kontrollerar om filen är öppen innan den stängs.
Mönster 2: Den villkorliga ÖPPNA
En fil öppnas villkorligt, endast när ett visst bearbetningsläge är aktivt. Men STÄNGNINGEN är villkorslös och inträffar i alla exekveringsvägar, inklusive de där filen aldrig öppnades.
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.
Denna defekt är osynlig vid testning om testerna alltid körs i FULL-läge. Den uppstår i produktion vid den första körningen i PARTIAL-läge.
Mönster 3: UTFÖR över kompileringsenheter
I program som använder CALL för att anropa underprogram kan en fil som öppnats i huvudprogrammet skickas till ett underprogram som stänger den, varefter huvudprogrammet stänger den igen.
cobol
*> Main program
CALL 'SUBPROG1' USING CUSTOMER-FILE-STATUS
*> SUBPROG1 closes CUSTOMER-FILE internally
CLOSE CUSTOMER-FILE *> double close
Detta mönster kräver interprocedural analys , där filtillstånd spåras över CALL-gränsen in i delprogrammets beteende, vilket enkel intraprogramanalys inte kan upptäcka.
Vad en statisk analysator behöver för att göra detta bra
Inte alla statiska analysverktyg hanterar COBOL-filtillståndsanalys med samma djup. Här är en checklista för beslutsfattande för att utvärdera kapaciteten:
Hanterar verktyget PERFORM-kedjor? COBOL-program använder PERFORM för att anropa namngivna stycken och avsnitt. Filåtgärder inuti ett PERFORM-mål måste vara synliga för anroparens tillståndsspårning.
Hanterar verktyget inline PERFORM VARYING (loopar)? Loopdetektering krävs för att identifiera loopdominerade ÖPPNA/STÄNGA-operationer.
Spårar den tillstånd över GO TO? Äldre COBOL-program använder GO TO i stor utsträckning. En analysator som inte kan följa GO TO-kanterna i kontrollflödesgrafen kommer att missa hela klasser av defekter.
Hanterar den COPY och REPLACE? Filhanteringskod finns ofta i COPY-medlemmar. En analysator som inte expanderar COPY-medlemmar före analysen kommer att missa operationer som definierats i inkluderad kod.
Kontrollerar den användningen av FILE STATUS? En fullständig analys kontrollerar inte bara om FILE STATUS deklareras utan om den faktiskt kontrolleras efter varje operation.
Utför den interprocedurell analys? Anropade delprogram som utför filoperationer skapar tillståndsberoenden mellan program. Sann täckning kräver att man följer anropskedjor.
Viktig slutsats: Ett verktyg som bara kontrollerar inom ett enda stycke eller avsnitt kommer att missa de flesta verkliga fel. De fel som är viktiga i produktionen, de som tog år att uppstå och timmar att diagnostisera, är de som sträcker sig över flera avsnitt, villkorliga grenar och så kallade rutiner.
Vad man ska göra med resultaten: Ett prioriteringsramverk
När statisk analys avslöjar filfel är inte alla fynd likadana. Så här prioriterar du dem:
Åtgärda omedelbart (innan nästa batchkörning):
- Dubbel ÖPPNA i valfri exekveringsväg där FILSTATUS 41 skulle orsaka ett fel
- STÄNG utan ÖPPEN i sökvägar som körs i produktion
- Saknar CLOSE på felutgångsvägar för VSAM-filer (risk för skrivintegritet)
Schema för nästa sprint:
- Loopdominerad ÖPPNA/STÄNGA med mätbar effekt av batchfönstret
- Saknade FILE STATUS-kontroller på kritiska filer (granskning, transaktion, rapport)
- Villkorlig ÖPPNING med villkorlig STÄNGNING i flerlägesprogram
Spårning och adress under nästa moderniseringspass:
- Saknade FILE STATUS-deklarationer
- STÄNG endast på normala utgångsvägar (OS hanterar det, men dålig praxis)
- Interprocedurella fel där korrigeringen kräver samordning av ändringar över flera program
Hur SMART TS XL Analyserar COBOL-filens tillstånd
SMART TS XLÄr statisk kodanalys bygger en kontrollflödesmodell för varje COBOL-program i miljön, expanderar COPY-medlemmar, följer PERFORM-kedjor, spårar GO TO-kanter och sprider filtillstånd genom varje gren i varje villkorsstyrt element. Det är inte en mönstermatchningsskanning; det är en strukturell modell av vad programmet faktiskt gör vid varje nåbar punkt i sin exekvering.
Funktionen för mappning av applikationsberoenden utökar detta till den interprocedurala dimensionen: när ett COBOL-program ANROPAR ett delprogram som utför filoperationer, representerar beroendemappningen den relationen, vilket möjliggör analys som korsar kompileringsenhetsgränser. Dubbla OPEN-defekter som sträcker sig över ett huvudprogram och ett anropat delprogram är synliga i den strukturella modellen på ett sätt som de inte är i någon intraprogramanalys.
Företagssökfunktionen gör resultaten användbara i stor skala: hitta alla program i portföljen som öppnar en specifik datamängd, varje COPY - medlem som innehåller en CLOSE-sats, alla program som har ett PERFORM-mål som innehåller en OPEN, över miljontals rader COBOL på några sekunder. För ett moderniseringsteam som förbereder sig för att migrera en batch-arbetsbelastning till molnet förvandlar den här sökfunktionen en veckolång manuell granskning till en riktad fråga.
JCL -expansionsfunktionen lägger till den operativa kontexten: vilka JCL-jobbsteg anropar varje program, vilka dataset varje DD-sats refererar till och hur filhanteringen i COBOL-koden ansluter till de fysiska dataset som definieras i JCL. En CLOSE-defekt på en fil som JCL definierar som en kritisk utdataset har högre prioritet än samma defekt på en temporär arbetsfil, och den prioriteringen kräver att man känner till JCL-kontexten för varje COBOL-program.
Den bredare lärdomen: Filtillstånd är bara en dimension
Redundanta filoperationer är ett specifikt exempel på ett mer generellt problem: COBOL-program som har utvecklats under årtionden innehåller tillståndsberoende beteenden, filtillstånd, växeltillstånd, räknartillstånd, som bara förstås korrekt genom att spåra alla möjliga exekveringsvägar genom hela kontrollflödesgrafen.
Mänsklig granskning av den här typen av kod är långsam, ofullständig och inkonsekvent. Olika utvecklare hittar olika fel. Samma utvecklare som granskar samma program två gånger hittar olika fel. Statisk analys är systematisk: den tillämpar samma regler på varje sökväg i varje program, varje gång, utan trötthet eller antaganden.
För team som hanterar stora COBOL-portföljer, oavsett om det gäller löpande underhåll, äldre moderniseringsprogram eller efterlevnadsrevisioner, är utdelningen av systematisk filstatusanalys inte bara de fel som upptäcks. Det är förtroendet för att portföljen har analyserats fullständigt och att de fel som kvarstår är kända snarare än dolda.


