Obsługa plików w języku COBOL jest pozornie prosta. Deklarujesz plik w DZIALE ŚRODOWISKA, opisujesz układ jego rekordów w DZIALE DANYCH, a w DZIALE PROCEDUR używa się instrukcji OPEN, READ lub WRITE i CLOSE. Cztery czasowniki, jeden cykl życia. Problem polega na tym, że programy w języku COBOL rzadko pozostają proste – kumulują logikę, ścieżki wyjątków, rozgałęzienia warunkowe i wywołania PERFORM przez dekady konserwacji. To, co zaczyna się jako czysty schemat pojedynczego otwarcia i zamknięcia, po cichu przekształca się w coś bardziej złożonego: pliki otwierane dwukrotnie w jednej ścieżce wykonania, instrukcje CLOSE wykonywane, gdy żaden plik nie jest otwarty, wyjścia błędów, które całkowicie wykraczają poza CLOSE.
Żaden z tych problemów nie jest od razu widoczny. Program się kompiluje. Często działa bezbłędnie na testowanych danych wejściowych. Po cichu zawodzi przy nieoczekiwanych kombinacjach danych wejściowych lub obniża wydajność okna wsadowego tak stopniowo, że nikt nie łączy przyczyny ze skutkiem. Analiza statyczna wykrywa je, zanim cokolwiek się wydarzy.
Wykrywanie wycieków w każdym języku
SMART TS XL mapuje długotrwałe łańcuchy odniesień i nieograniczone struktury danych w całej bazie kodu.
Więcej informacjiCztery wady stanu pliku, które warto znaleźć
Zanim przejdziemy do mechaniki wykrywania, oto jasna klasyfikacja tego, czego szukasz. Nie wszystkie problemy z plikami COBOL są sobie równe.
| Wada | Co dzieje się w czasie wykonywania | Dotkliwość |
|---|---|---|
| Podwójne OTWARTE | OTWÓRZ w już otwartym pliku → STATUS PLIKU 41 lub abend | Wysoki |
| ZAMKNIJ bez wcześniejszego OTWÓRZ | ZAMKNIJ plik, który nigdy nie został otwarty → STATUS PLIKU 42 lub zakończenie awaryjne | Wysoki |
| Brakuje CLOSE przy normalnym wyjściu | Plik pozostawiony otwarty w trybie STOP RUN → system operacyjny go zamyka, ale nieopróżnione bufory grożą utratą danych | Średni |
| Brakuje CLOSE przy wyjściu z błędu | Program kończy się niepowodzeniem przy otwartym pliku → potencjalne uszkodzenie rekordu w plikach VSAM | Wysoki |
| Nadmiarowe OTWÓRZ/ZAMKNIJ w pętli | Plik otwierany i zamykany przy każdej iteracji → poważne obciążenie wejścia/wyjścia | Średnio-wysoki |
Kluczowy wniosek: Defekty o najwyższym stopniu istotności, podwójne OTWÓRZ i ZAMKNIJ bez OPEN, powodują natychmiastowe awarie środowiska wykonawczego lub zagrożenia integralności danych. Defekty wydajności (otwarcie/zamknięcie na poziomie pętli) nie powodują żadnych błędów, a jedynie powolne zadania wsadowe, których przyczyny nikt nie ustalił.
Dlaczego trudno to znaleźć ręcznie
Wyzwaniem nie jest identyfikacja wzorca. Każdy programista wie, że nie należy otwierać pliku dwa razy. Problemem jest nieliniowość przepływu sterowania w COBOL-u, która sprawia, że ręczne śledzenie jest zawodne.
Rozważmy program o takiej strukturze:
kobol
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.
Czy potrafisz zlokalizować defekt bez śledzenia każdej ścieżki wykonania? Jeśli WS-ERROR-FLAG jest ustawiony na 1 wewnątrz PROCESS-ONE-RECORD (być może za pomocą wywołanego podprogramu), sterowanie przepływa do ERROR-EXIT, co zamyka plik i zatrzymuje działanie. To prawda. Ale jeśli WS-ERROR-FLAG is nie ustaw, pętla się kończy, PROCESS-RECORDS zwroty i TERMINATION biegnie, co również zamyka CUSTOMER-FILE. Dwa zamknięcia, jedno otwarcie. STATUS PLIKU w czasie wykonywania 42.
To prosty program składający się z trzech sekcji. Prawdziwe programy składają się z dwudziestu sekcji, warunkowych wywołań PERFORM, instrukcji GO TO w starszym kodzie oraz procedur obsługi wyjątków, które same wywołują inne procedury. Ręczne śledzenie jest nie tylko podatne na błędy, ale i trudne do wykonania.
Jak modele analizy statycznej zapisują stan pliku
Analiza statyczna pozwala na wykrywanie tych defektów poprzez tworzenie grafu przepływu sterowania programu i propagowanie stanu pliku wzdłuż każdej ścieżki.
Analiza przypisuje każdemu plikowi zmienną stanu z trzema możliwymi wartościami:
CLOSEDplik nie został otwarty lub został pomyślnie zamkniętyOPEN, plik został otwarty, ale jeszcze nie zamkniętyUNKNOWN, stanu nie można określić statycznie (np. warunkowe otwarcie w gałęzi nie jest w pełni przeanalizowane)
Przy każdym poleceniu OPEN analiza sprawdza: czy ten plik jest już w stanie OPEN? Jeśli tak → podwójna wada OTWARTA.
Przy każdym poleceniu CLOSE: czy ten plik jest w stanie CLOSED or UNKNOWN? Jeśli ZAMKNIĘTE → zamknij bez otwartej wady.
W każdej ścieżce do STOP RUN lub EXIT PROGRAM: czy jakiś plik jest nadal w stanie OPEN? Jeśli tak → brak bliskiej wady.
W przypadku pętli analiza sprawdza, czy polecenie OPEN lub CLOSE jest zdominowane przez nagłówek pętli, co oznacza, że jest wykonywane przy każdej iteracji.
Uważaj: Najtrudniejszymi przypadkami dla każdego analizatora są wywołania PERFORM w procedurach współdzielonych. Jeśli
ERROR-HANDLERjest wywoływany z dwunastu różnych miejsc w programie, stan pliku w momencie wywołania PERFORM decyduje o tym, czy zamknięcie wewnątrzERROR-HANDLERjest poprawny, czy błędny. Analizator, który nie propaguje stanu przez łańcuchy PERFORM, będzie generował wyniki fałszywie negatywne (brakujące rzeczywiste defekty) lub fałszywie pozytywne (oznaczające poprawny kod).
OTWÓRZ/ZAMKNIJ na poziomie pętli: wada wydajności bez kodu błędu
Ten wzorzec nie powoduje błędów w czasie wykonywania ani anomalii w STANIE PLIKU. Po prostu działa wolno, potencjalnie o rzędy wielkości wolniej niż to konieczne.
kobol
*> 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.
O ile plik nie jest fizycznie podzielony na regiony, takie podejście powoduje niepotrzebne obciążenie. W praktyce lepiej byłoby otworzyć plik raz, odczytać wszystkie rekordy i zastosować filtrowanie w pamięci lub za pomocą logiki.
Każde polecenie OPEN w pliku VSAM obejmuje wyszukiwanie w katalogu, inicjalizację bloku ACB i alokację puli buforów. Każde polecenie CLOSE opróżnia bufory, aktualizuje katalog i zwalnia blok ACB. W przypadku pliku z dziesięcioma regionami, dzieje się to dziesięć razy zamiast jednego. W przypadku pliku z 10 000 rekordów i tysiącem regionów, obliczenia stają się uciążliwe.
kobol
*> 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.
Analiza statyczna wykrywa to zjawisko poprzez identyfikację instrukcji OPEN i CLOSE, które są zdominowane przez pętlę, tzn. każde wykonanie ciała pętli powoduje wykonanie instrukcji OPEN lub CLOSE. Wykrycie wymaga, aby graf przepływu sterowania reprezentował strukturę pętli, a nie tylko sekwencję instrukcji.
STATUS PLIKU: Sygnał stanu pliku Twojego programu, jeśli go sprawdzisz
Każda operacja na plikach w języku COBOL ustawia pole FILE STATUS zdefiniowane we wpisie FILE-CONTROL. Program, który sprawdza FILE STATUS po każdym OTWARCIU, ODCZYCIE, ZAPISIE i ZAMKNIĘCIU, może wykryć i zareagować na każdą anomalię stanu pliku w czasie wykonywania. Program, który ignoruje FILE STATUS, działa na ślepo.
Lista kontrolna: kody STATUSU PLIKÓW, które powinien znać każdy programista COBOL
00, Pomyślne zakończenie10Koniec pliku (ODCZYTAJ: brak więcej rekordów)35, Plik nie znaleziony (OTWÓRZ WEJŚCIE: plik nie istnieje)41, Plik już otwarty (OTWÓRZ dla pliku w stanie OTWARTY)42Plik nie jest otwarty (ZAMKNIĘTY lub ODCZYTAJ plik w stanie ZAMKNIĘTYM)47, Próba ODCZYTU pliku nie została otwarta. WEJŚCIE lub IO48, Próba zapisu w pliku nie została otwarta WYJŚCIE, IO lub ROZSZERZENIE97Plik został pomyślnie otwarty (specyficzne dla IBM, niektóre środowiska)
kobol
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.
Uważaj: Częstym błędem konserwacyjnym jest deklarowanie STATUSU PLIKU w pozycji KONTROLA PLIKÓW, ale nigdy nieodwoływanie się do niego
WS-CUST-FILE-STATUSw DZIALE PROCEDUR. Pole jest wypełniane po każdej operacji na pliku, ale jeśli żaden kod go nie sprawdza, program działa po wystąpieniu błędów. Analiza statyczna może oznaczyć ten wzorzec: STATUS PLIKU zadeklarowany, ale nigdy nieodwołany w logice warunkowej.
Trzy rzeczywiste wzorce języka COBOL powodujące defekty
Wzorzec 1: Problem wspólnego wyjścia z błędu
Program składa się z wielu sekcji przetwarzania, z których każda ma własną procedurę obsługi błędów. Kilka procedur obsługi błędów zamyka plik przed zwróceniem go. Standardowa procedura kończenia również zamyka plik. Jeśli wystąpi błąd i odzyskiwanie danych po przejściu procedury obsługi błędów zostanie zakończone, plik zostanie zamknięty dwukrotnie.
kobol
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 przenosi kontrolę bezpośrednio do TERMINATION, który wykonuje własne CLOSE CUSTOMER-FILE. STATUS PLIKU 42.
Poprawka: Użyj jednej scentralizowanej procedury zamykania. Każda ścieżka wyjścia wywołuje tę samą procedurę, która sprawdza, czy plik jest otwarty przed zamknięciem.
Wzorzec 2: Warunkowe OTWARCIE
Plik jest otwierany warunkowo, tylko gdy aktywny jest określony tryb przetwarzania. Natomiast polecenie CLOSE jest bezwarunkowe i występuje w każdej ścieżce wykonywania, także w tych, w których plik nigdy nie został otwarty.
kobol
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.
Ten defekt jest niewidoczny podczas testów, jeśli testy są zawsze uruchamiane w trybie PEŁNYM. Pojawia się w środowisku produkcyjnym podczas pierwszego uruchomienia w trybie CZĘŚCIOWYM.
Wzorzec 3: PERFORM w jednostkach kompilacji
W programach, które używają polecenia CALL do wywoływania podprogramów, plik otwarty w programie głównym może zostać przekazany do podprogramu, który go zamknie, a następnie program główny ponownie go zamknie.
kobol
*> Main program
CALL 'SUBPROG1' USING CUSTOMER-FILE-STATUS
*> SUBPROG1 closes CUSTOMER-FILE internally
CLOSE CUSTOMER-FILE *> double close
Ten wzorzec wymaga analizy międzyproceduralnej , śledzenia stanu pliku przez granicę CALL w zachowaniu podprogramu, czego nie można wykryć za pomocą prostej analizy wewnątrzprogramowej.
Czego potrzebuje analizator statyczny, aby dobrze to zrobić
Nie wszystkie narzędzia do analizy statycznej obsługują analizę stanu plików COBOL z równą dokładnością. Oto lista kontrolna decyzji do oceny możliwości:
Czy narzędzie obsługuje łańcuchy PERFORM? Programy COBOL używają PERFORM do wywoływania nazwanych akapitów i sekcji. Operacje na plikach wewnątrz celu PERFORM muszą być widoczne dla śledzenia stanu wywołującego.
Czy narzędzie obsługuje pętle PERFORM VARYING? Wykrywanie pętli jest wymagane do identyfikacji operacji OTWÓRZ/ZAMKNIJ zdominowanych przez pętle.
Czy śledzi stan w GO TO? Starsze programy COBOL intensywnie korzystają z GO TO. Analizator, który nie jest w stanie śledzić krawędzi GO TO w grafie przepływu sterowania, pominie całe klasy defektów.
Czy obsługuje operacje COPY i REPLACE? Kod obsługi plików często znajduje się w elementach COPY. Analizator, który nie rozwinie elementów COPY przed analizą, pominie operacje zdefiniowane w dołączonym kodzie.
Czy sprawdza użycie STATUSU PLIKU? Pełna analiza sprawdza nie tylko, czy STATUS PLIKU jest zadeklarowany, ale także, czy jest on faktycznie sprawdzany po każdej operacji.
Czy wykonuje analizę międzyproceduralną? Podprogramy CALL, które wykonują operacje na plikach, tworzą międzyprogramowe zależności stanu. Prawdziwe pokrycie wymaga następujących łańcuchów CALL.
Kluczowy wniosek: Narzędzie, które sprawdza tylko jeden akapit lub sekcję, przeoczy większość rzeczywistych defektów. Defekty, które mają znaczenie w środowisku produkcyjnym, te, których pojawienie się zajęło lata, a zdiagnozowanie godzin, to te, które obejmują wiele sekcji, gałęzi warunkowych i procedur.
Co zrobić z wynikami: Ramy ustalania priorytetów
Gdy analiza statyczna ujawnia wady plików, nie wszystkie wyniki są takie same. Oto jak je sklasyfikować:
Napraw natychmiast (przed następnym uruchomieniem partii):
- Podwójne OTWARCIE w dowolnej ścieżce wykonywania, w której STATUS PLIKU 41 spowodowałby nieprawidłowe zakończenie
- CLOSE bez OPEN w ścieżkach wykonywanych w środowisku produkcyjnym
- Brak zamknięcia ścieżek wyjścia błędów dla plików VSAM (ryzyko naruszenia integralności zapisu)
Harmonogram następnego sprintu:
- Zdominowane przez pętlę OTWÓRZ/ZAMKNIJ z mierzalnym wpływem okna wsadowego
- Brak kontroli STATUSU PLIKU w przypadku plików krytycznych (audyt, transakcja, raport)
- Warunkowe OTWÓRZ z bezwarunkowym ZAMKNIJ w programach wielomodowych
Śledź i zaadresuj podczas następnego przeglądu modernizacyjnego:
- Brak deklaracji FILE STATUS
- ZAMKNIJ tylko na normalnych ścieżkach wyjścia (system operacyjny sobie z tym radzi, ale to zła praktyka)
- Usterki międzyproceduralne, których naprawa wymaga skoordynowania zmian w wielu programach
W jaki sposób SMART TS XL Analizuje stan pliku COBOL
SMART TS XL'S statyczna analiza kodu Buduje model przepływu sterowania dla każdego programu COBOL w środowisku, rozwijając elementy COPY, podążając za łańcuchami PERFORM, śledząc krawędzie GO TO i propagując stan pliku przez każdą gałąź każdego warunku. Nie jest to skanowanie dopasowujące wzorce; jest to model strukturalny tego, co program faktycznie robi w każdym osiągalnym punkcie swojego wykonania.
Możliwość mapowania zależności aplikacji rozszerza to na wymiar międzyproceduralny: gdy program COBOL wywołuje podprogram wykonujący operacje na plikach, mapa zależności reprezentuje tę relację, umożliwiając analizę wykraczającą poza granice jednostek kompilacji. Podwójne defekty typu OPEN, obejmujące program główny i wywoływany podprogram, są widoczne w modelu strukturalnym w sposób, w jaki nie są widoczne w żadnej analizie wewnątrzprogramowej.
Funkcja wyszukiwania korporacyjnego umożliwia wykorzystanie wyników na dużą skalę: znajdź każdy program w portfolio, który otwiera określony zestaw danych, każdy element COPY zawierający instrukcję CLOSE, każdy program z celem PERFORM zawierającym instrukcję OPEN, w milionach wierszy kodu COBOL w ciągu kilku sekund. Dla zespołu modernizacyjnego przygotowującego się do migracji obciążenia wsadowego do chmury, ta funkcja wyszukiwania zamienia wielotygodniowy ręczny audyt w ukierunkowane zapytanie.
Możliwość rozszerzenia JCL dodaje kontekst operacyjny: które kroki zadania JCL wywołują każdy program, do których zestawów danych odwołuje się każde polecenie DD oraz w jaki sposób obsługa plików w kodzie COBOL łączy się z fizycznymi zestawami danych zdefiniowanymi w JCL. Defekt CLOSE w pliku, który JCL definiuje jako krytyczny zestaw danych wyjściowych, ma wyższy priorytet niż ten sam defekt w tymczasowym pliku roboczym, a ta priorytetyzacja wymaga znajomości kontekstu JCL każdego programu COBOL.
Szersza lekcja: stan pliku to tylko jeden wymiar
Nadmiarowe operacje na plikach stanowią szczególny przykład bardziej ogólnego problemu: programy COBOL, które ewoluowały przez dziesięciolecia, zawierają zachowania zależne od stanu, stanu pliku, stanów przełączników, stanów liczników, które można prawidłowo zrozumieć jedynie poprzez prześledzenie każdej możliwej ścieżki wykonania w pełnym grafie przepływu sterowania.
Ludzki przegląd tego rodzaju kodu jest powolny, niekompletny i niespójny. Różni programiści znajdują różne defekty. Ten sam programista, przeglądając ten sam program dwukrotnie, znajduje różne defekty. Analiza statyczna jest systematyczna: stosuje te same reguły do każdej ścieżki w każdym programie, za każdym razem, bez zmęczenia i bez założeń.
Dla zespołów zarządzających dużymi portfelami COBOL, niezależnie od tego, czy chodzi o bieżącą konserwację, modernizację starszych wersji oprogramowania, czy audyty zgodności, korzyścią z systematycznej analizy stanu plików są nie tylko znalezione defekty. To pewność, że portfel został kompleksowo przeanalizowany, a pozostałe defekty są znane, a nie ukryte.