טיפול בקבצים ב-COBOL הוא פשוט באופן מטעה על פני השטח. אתה מכריז על קובץ ב-ENVIRONMENT DIVISION, מתאר את פריסת הרשומה שלו ב-DATA DIVISION, ומשתמש ב-OPEN, READ או WRITE, ו-CLOSE ב-PRODUCTION DIVISION. ארבעה פעלים, מחזור חיים אחד. הבעיה היא שתוכניות COBOL כמעט ולא נשארות פשוטות, הן צוברות לוגיקה, נתיבי חריגים, ענפים מותנים וקריאות PERFORM במשך עשרות שנים של תחזוקה. מה שמתחיל כתבנית נקייה של פתיחה אחת וסגירה אחת, הופך בשקט למשהו מורכב יותר: קבצים שנפתחים פעמיים בנתיב ביצוע יחיד, פקודות CLOSE שפועלות כאשר אין קובץ פתוח, שגיאה יוצאת לחלוטין מהענף הזה מעבר ל-CLOSE.
אף אחת מהבעיות הללו אינה נראית לעין באופן מיידי. התוכנית מבצעת קומפילציה. לעתים קרובות היא פועלת ללא שגיאות, על הקלטים שאתה בודק. היא נכשלת בשקט על שילובי קלט שמעולם לא צפית להם, או פוגעת בביצועי חלון האצווה בצורה כה הדרגתית שאף אחד לא מקשר בין הסיבה לתוצאה. ניתוח סטטי מוצא אותן לפני שמשהו מזה קורה.
גילוי דליפות בכל שפה
SMART TS XL ממפה שרשראות ייחוס ארוכות טווח ומבני נתונים בלתי מוגבלים על פני בסיס הקוד המלא שלך.
מידע נוסףארבעת פגמי מצב הקובץ שכדאי למצוא
לפני שנכנס למכניקת הזיהוי, הנה טקסונומיה ברורה של מה שאתם מחפשים. לא כל בעיות קבצי COBOL נוצרות שוות.
| פגם | מה קורה בזמן ריצה | חומרה |
|---|---|---|
| פתוח כפול | פתיחה על קובץ שכבר פתוח → סטטוס קובץ 41 או ביטול | גָבוֹהַ |
| סגירה ללא פתיחה מוקדמת | סגור על קובץ שמעולם לא נפתח → סטטוס קובץ 42 או סגור | גָבוֹהַ |
| חסר סגירה ביציאה רגילה | קובץ שנותר פתוח ב-STOP RUN → מערכת ההפעלה סוגרת אותו, אך מאגרים שלא נמחקו מסתכנים באובדן נתונים | בינוני |
| חסר סגירה ביציאה משגיאה | התוכנית נסגרת עם קובץ פתוח → פגיעה אפשרית ברשומות בקבצי VSAM | גָבוֹהַ |
| פתיחה/סגירה מיותרת בלולאה | קובץ נפתח ונסגר בכל איטרציה → תקרת קלט/פלט חמורה | בינוני גבוה |
מסקנה עיקרית: הפגמים בעלי החומרה הגבוהה ביותר, פתיחה כפולה וסגירה ללא פתיחה, יוצרים כשלים מיידיים בזמן ריצה או סיכוני שלמות נתונים. פגמי הביצועים (פתיחה/סגירה ברמת הלולאה) אינם יוצרים שגיאה כלל, רק עבודות אצווה איטיות שאף אחד לא איתר את הגורם להן.
מה מקשה על מציאת זה ידנית
האתגר הוא לא לזהות את התבנית. כל מפתח יודע שאסור לפתוח קובץ פעמיים. האתגר הוא שזרימת הבקרה של 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.
האם ניתן לאתר את הפגם מבלי לעקוב אחר כל נתיב ביצוע? WS-ERROR-FLAG מוגדר ל-1 בפנים PROCESS-ONE-RECORD (אולי על ידי תת-תוכנית שנקראה), הבקרה זורמת אל ERROR-EXIT, אשר סוגר את הקובץ ועוצר. זה נכון. אבל אם WS-ERROR-FLAG is לֹא מוגדר, הלולאה הושלמה, PROCESS-RECORDS החזרות, ו TERMINATION ריצות, אשר גם נסגרות CUSTOMER-FILEשתי סגירות, פתיחה אחת. סטטוס קובץ בזמן ריצה 42.
זוהי תוכנית פשוטה בת שלושה חלקים. לתוכניות אמיתיות יש עשרים חלקים, קריאות PERFORM מותנות, פקודות GO TO בקוד מדור קודם, ושגרות טיפול בחריגים שקוראות בעצמן לרוטינות אחרות. מעקב ידני אינו רק מועד לשגיאות, הוא אינו ניתן לניהול.
כיצד ניתוח סטטי מדמה את מצב הקובץ
ניתוח סטטי מזהה פגמים אלה על ידי בניית גרף זרימת בקרה של התוכנית והפצת מצב הקובץ לאורך כל נתיב.
הניתוח מקצה לכל קובץ משתנה מצב עם שלושה ערכים אפשריים:
CLOSED, הקובץ לא נפתח, או נסגר בהצלחהOPENהקובץ נפתח ועדיין לא נסגרUNKNOWN, לא ניתן לקבוע את המצב באופן סטטי (למשל, פתיחה מותנית בענף שלא נותח במלואו)
בכל פקודה OPEN, הניתוח בודק: האם קובץ זה כבר במצב OPENאם כן → פגם פתוח כפול.
בכל משפט CLOSE: האם קובץ זה במצב CLOSED or UNKNOWNאם סגור → סגור ללא פגם פתוח.
בכל נתיב ל-STOP RUN או EXIT PROGRAM: האם קובץ כלשהו עדיין במצבו? OPENאם כן → פגם סגור חסר.
עבור לולאות, הניתוח בודק האם פקודה OPEN או CLOSE נשלטת על ידי כותרת לולאה, כלומר היא מבצעת כל איטרציה.
היזהר: המקרים הקשים ביותר עבור כל מנתח הם קריאות PERFORM לתוך שגרות משותפות. אם
ERROR-HANDLERנקרא משנים עשר מקומות שונים בתוכנית, מצב הקובץ בנקודת הקריאה של PERFORM קובע האם סגירה בתוךERROR-HANDLERנכון או שגוי. מנתח שאינו מפיץ מצב דרך שרשראות PERFORM יפיק תוצאות שליליות שגויות (חסרי פגמים אמיתיים) או תוצאות חיוביות שגויות (סימון קוד נכון).
פתיחה/סגירה ברמת הלולאה: פגם ביצועים ללא קוד שגיאה
תבנית זו אינה מייצרת שגיאות זמן ריצה ואינה אנומליה ב-FILE STATUS. היא פשוט פועלת לאט, אולי אפילו סדרי גודל איטיים יותר מהנדרש.
קובול
*> 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.
אלא אם כן הקובץ מחולק פיזית לפי אזור, גישה זו גורמת לתקורה מיותרת. בפועל, עדיף לפתוח את הקובץ פעם אחת, לקרוא את כל הרשומות ולהחיל סינון בזיכרון או באמצעות לוגיקה.
כל פתיחה (OPEN) בקובץ VSAM כרוכה בחיפוש קטלוג, אתחול ACB והקצאת מאגר מאגרים. כל סגירה (CLOSE) מרוקנת את המאגרים, מעדכנת את הקטלוג ומשחררת את ה-ACB. עבור קובץ עם עשרה אזורים, זה קורה עשר פעמים במקום פעם אחת. עבור קובץ עם 10,000 רשומות ואלף אזורים, החישוב הופך לכואב.
קובול
*> 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.
ניתוח סטטי מזהה זאת על ידי זיהוי פקודות OPEN ו-CLOSE הנשלטות על ידי לולאה, כלומר, כל ביצוע של גוף הלולאה מבצע את ה-OPEN או CLOSE. הזיהוי דורש שגרף זרימת הבקרה ייצג את מבנה הלולאה, ולא רק את רצף הפקודות.
סטטוס קובץ: אות מצב הקובץ של התוכנית שלך, אם תבדוק אותו
כל פעולת קובץ COBOL מגדירה את השדה FILE STATUS המוגדר בערך FILE-CONTROL. תוכנית שבודקת את FILE STATUS לאחר כל OPEN, READ, WRITE ו-CLOSE יכולה לזהות ולהגיב לכל אנומליה במצב קובץ בזמן ריצה. תוכנית שמתעלמת מ-FILE STATUS טסה בעיוורון.
רשימת בדיקה: קודי סטטוס קובץ שכל מפתח COBOL צריך להכיר
00, השלמה מוצלחת10, סוף קובץ (קריאה: אין עוד רשומות)35, קובץ לא נמצא (פתח קלט: קובץ לא קיים)41הקובץ כבר פתוח (OPEN על קובץ במצב OPEN)42, הקובץ לא נפתח (סגור או קריאה עבור קובץ במצב סגור)47ניסיון קריאה בקובץ שלא נפתח, קלט או קלט/פלט48ניסיון כתיבה על קובץ שלא נפתח: OUTPUT, IO או EXTEND97, הקובץ נפתח בהצלחה (ספציפי ל-IBM, סביבות מסוימות)
קובול
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.
היזהר: שגיאת תחזוקה נפוצה היא הצהרת FILE STATUS בערך FILE-CONTROL אך לעולם לא הפניה אליו
WS-CUST-FILE-STATUSב-PROCEDURE DIVISION. השדה מאוכלס לאחר כל פעולת קובץ, אך אם אף קוד לא בודק אותו, התוכנית תרוץ על פני שגיאות בשקט. ניתוח סטטי יכול לסמן דפוס זה: FILE STATUS הוצהר אך מעולם לא הופנה אליו בלוגיקה מותנית.
שלוש תבניות COBOL מהעולם האמיתי שגורמות לפגמים
תבנית 1: בעיית השגיאה-יציאה המשותפת
לתוכנית יש מספר מקטעי עיבוד, שלכל אחד מהם מטפל שגיאות משלו. מספר מטפלי שגיאות סוגרים את הקובץ לפני החזרה. שגרת הסיום הרגילה סוגרת גם היא את הקובץ. אם מתרחשת שגיאה והשחזור ממשיך מעבר למטפל השגיאות, הקובץ נסגר פעמיים.
קובול
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 מעביר שליטה ישירות אל TERMINATION, אשר מבצעת את עצמה CLOSE CUSTOMER-FILEסטטוס קובץ 42.
תיקון: השתמשו בשגרת סגירה מרכזית אחת. כל נתיב יציאה קורא לאותה שגרה, שבודקת האם הקובץ פתוח לפני הסגירה.
תבנית 2: הפתיחה המותנית
קובץ נפתח באופן מותנה, רק כאשר מצב עיבוד מסוים פעיל. אבל הסגירה אינה מותנית, ומתרחשת בכל נתיב ביצוע, כולל אלה שבהם הקובץ מעולם לא נפתח.
קובול
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.
פגם זה אינו נראה בבדיקות אם הבדיקות רצות תמיד במצב מלא. הוא צף בייצור בהרצה הראשונה במצב חלקי.
תבנית 3: ביצוע על פני יחידות קומפילציה
בתוכניות המשתמשות ב-CALL כדי להפעיל תת-תוכניות, קובץ שנפתח בתוכנית הראשית עשוי להיות מועבר לתת-תוכנית שסוגרת אותו, ואז התוכנית הראשית סוגרת אותו שוב.
קובול
*> Main program
CALL 'SUBPROG1' USING CUSTOMER-FILE-STATUS
*> SUBPROG1 closes CUSTOMER-FILE internally
CLOSE CUSTOMER-FILE *> double close
דפוס זה דורש ניתוח בין-פרוצדורלי , מעקב אחר מצב הקובץ מעבר לגבול ה-CALL אל תוך התנהגות תת-התוכנית, דבר שניתוח פשוט תוך-תוכנית אינו יכול לזהות.
מה מנתח סטטי צריך כדי לעשות זאת היטב
לא כל כלי הניתוח הסטטי מטפלים בניתוח מצב קבצי COBOL באותה עומק. הנה רשימת בדיקה להערכת יכולות:
האם הכלי מטפל בשרשראות PERFORM? תוכניות COBOL משתמשות ב-PERFORM כדי לקרוא לפסקאות וסעיפים בעלי שם. פעולות קבצים בתוך יעד PERFORM חייבות להיות גלויות למעקב המצב של הקורא.
האם הכלי מטפל ב-inline PERFORM VARYING (לולאות)? זיהוי לולאות נדרש כדי לזהות פעולות OPEN/CLOSE הנשלטות על ידי לולאה.
האם זה עוקב אחר מצב לאורך GO TO? תוכניות COBOL מדור קודם משתמשות ב-GO TO בהרחבה. מנתח שאינו יכול לעקוב אחר קצוות GO TO בגרף זרימת הבקרה יפספס מחלקות שלמות של פגמים.
האם הוא מטפל ב-COPY וב-REPLACE? קוד לטיפול בקבצים נמצא לרוב באיברי COPY. מנתח שאינו מרחיב איברי COPY לפני הניתוח יחמיץ פעולות המוגדרות בקוד הכלול.
האם זה בודק את השימוש ב-FILE STATUS? ניתוח מלא בודק לא רק האם FILE STATUS מוצהר, אלא האם הוא אכן נבדק לאחר כל פעולה.
האם הוא מבצע ניתוח בין-פרוצדורלי? תת-תוכניות שנקראו ומבצעות פעולות קבצים יוצרות תלויות מצב בין-תוכניות. כיסוי אמיתי דורש ביצוע שרשראות CALL.
מסקנה חשובה: כלי שבודק רק פסקה או מקטע בודד יחמיץ את רוב הפגמים בעולם האמיתי. הפגמים החשובים בייצור, אלה שלקח שנים להופיע ושעות לאבחון, הם אלה שמשתרעים על פני מקטעים מרובים, ענפים מותנים, ו"רוטינות".
מה לעשות עם התוצאות: מסגרת קביעת סדרי עדיפויות
כאשר ניתוח סטטי חושף פגמים בקבצים, לא כל הממצאים שווים. כך ניתן לדרג אותם:
תקן מיד (לפני ריצת האצווה הבאה):
- פתיחה כפולה בכל נתיב ביצוע שבו FILE STATUS 41 יגרום לשגיאה
- סגירה ללא פתיחה בנתיבים שמבוצעים בסביבת ייצור
- חסר סגירה בנתיבי יציאה משגיאות עבור קבצי VSAM (סיכון שלמות כתיבה)
לוח זמנים לספרינט הבא:
- פתיחה/סגירה הנשלטת על ידי לולאה עם השפעה מדידה של חלון אצווה
- בדיקות סטטוס קובץ חסרות בקבצים קריטיים (ביקורת, עסקה, דוח)
- פתיחה מותנית עם סגירה ללא תנאי בתוכניות מרובות מצבים
מעקב וכתובת במהלך מעבר המודרניזציה הבא:
- הצהרות סטטוס קובץ חסרות
- סגור רק בנתיבי יציאה רגילים (מערכת ההפעלה מטפלת בזה, אבל זה נוהג גרוע)
- פגמים בין-פרוצדוריים שבהם התיקון דורש תיאום שינויים בין תוכניות מרובות
איך SMART TS XL מנתח את מצב קובץ ה-COBOL
SMART TS XL"S ניתוח קוד סטטי בונה מודל זרימת בקרה של כל תוכנית COBOL בסביבה, מרחיב איברי COPY, עוקב אחר שרשראות PERFORM, עוקב אחר קצוות GO TO ומפיץ את מצב הקובץ דרך כל ענף של כל תנאי. זה לא סריקת התאמת תבניות; זהו מודל מבני של מה שהתוכנית עושה בפועל בכל נקודה נגישה בביצועה.
יכולת מיפוי התלות של היישומים מרחיבה זאת למימד הבין-פרוצדורלי: כאשר תוכנית COBOL קוראת לתת-תוכנית שמבצעת פעולות קבצים, מפת התלות מייצגת את הקשר הזה, ומאפשרת ניתוח שחוצה גבולות יחידות קומפילציה. פגמי OPEN כפולים המשתרעים על פני תוכנית ראשית ותת-תוכנית שנקראה גלויים במודל המבני באופן שבו הם אינם גלויים בשום ניתוח תוך-תוכניתי.
יכולת החיפוש הארגוני הופכת את התוצאות לפעולה בקנה מידה גדול: מצאו כל תוכנית בתיק העבודות שפותחת מערך נתונים ספציפי, כל חבר COPY המכיל משפט CLOSE, כל תוכנית שיש לה יעד PERFORM המכיל OPEN, על פני מיליוני שורות COBOL תוך שניות. עבור צוות מודרניזציה שמתכונן להעביר עומס עבודה של אצווה לענן, יכולת חיפוש זו הופכת ביקורת ידנית בת שבועות לשאילתה ממוקדת.
יכולת ההרחבה של JCL מוסיפה את ההקשר התפעולי: אילו שלבי משימת JCL מפעילים כל תוכנית, לאילו מערכי נתונים כל משפט DD מפנה, וכיצד טיפול הקבצים בקוד COBOL מתחבר למערכי הנתונים הפיזיים המוגדרים ב-JCL. פגם CLOSE בקובץ ש-JCL מגדיר כמערך נתונים קריטי הוא בעל עדיפות גבוהה יותר מאותו פגם בקובץ עבודה זמני, ותעדוף זה דורש הכרת ההקשר JCL של כל תוכנית COBOL.
הלקח הרחב יותר: מצב קובץ הוא רק מימד אחד
פעולות קבצים מיותרות הן דוגמה ספציפית לבעיה כללית יותר: תוכניות COBOL שהתפתחו במשך עשרות שנים מכילות התנהגויות תלויות-מצב, מצב קובץ, מצבי מיתוג ומצבי counter, אשר מובנות נכון רק על ידי מעקב אחר כל נתיב ביצוע אפשרי דרך גרף זרימת הבקרה המלא.
סקירה אנושית של קוד מסוג זה היא איטית, לא שלמה ולא עקבית. מפתחים שונים מוצאים פגמים שונים. אותו מפתח שבודק את אותה תוכנית פעמיים מוצא פגמים שונים. ניתוח סטטי הוא שיטתי: הוא מיישם את אותם כללים על כל נתיב בכל תוכנית, בכל פעם, ללא עייפות או הנחות.
עבור צוותים המנהלים תיקי COBOL גדולים, בין אם לצורך תחזוקה שוטפת, עבור תוכניות מודרניזציה מדור קודם או עבור ביקורות תאימות, התמורה של ניתוח שיטתי של מצב הקבצים אינה רק הפגמים שנמצאו. זוהי הביטחון שהתיק נותח במלואו, ושהפגמים שנותרו ידועים ולא נסתרים.


