系统检测到保护异常
The system detected a protection exception
我正在尝试使用 COBOL 的排序功能。
IDENTIFICATION DIVISION.
PROGRAM-ID. ******.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT IN-FILE ASSIGN TO IFILE.
SELECT OUT-FILE ASSIGN TO OFILE.
SELECT SORT-FILE ASSIGN TO SORTWK.
DATA DIVISION.
FILE SECTION.
SD SORT-FILE.
01 SORT-REC.
05 S-NAME PIC X(20).
05 S-ADDRESS PIC X(20).
05 S-ID PIC 9(9).
05 S-CREDITS PIC 99.
05 FILLER PIC X(29).
FD IN-FILE.
01 IN-REC.
05 IN-NAME PIC X(20).
05 IN-ADDRESS PIC X(20).
05 IN-ID PIC 9(9).
05 IN-CREDITS PIC 99.
05 FILLER PIC X(29).
FD OUT-FILE.
01 OUT-REC PIC X(80).
WORKING-STORAGE SECTION.
01 WS-WORK-AREA.
05 EOF-SW PIC X VALUE SPACES.
01 WS-DETAIL-LINES.
05 RPT-LINE.
10 OUT-NAME PIC X(20).
10 OUT-ADDRESS PIC X(20).
10 OUT-ID PIC 9(9).
10 OUT-CREDITS PIC 99.
10 FILLER PIC X(29) VALUE SPACES.
PROCEDURE DIVISION.
MAIN-RTN.
SORT SORT-FILE
ON ASCENDING KEY S-ID
INPUT PROCEDURE READ-RELEASE
OUTPUT PROCEDURE RETURN-WRITE.
STOP RUN.
OPEN-FILES-RTN.
OPEN INPUT IN-FILE.
OPEN OUTPUT OUT-FILE.
OPEN-FILES-RTN-EXIT. EXIT.
READ-RELEASE.
PERFORM OPEN-FILES-RTN.
PERFORM READ-INPUT
UNTIL EOF-SW = 'F'.
READ-RELEASE-RTN-EXIT. EXIT.
READ-INPUT.
READ IN-FILE
AT END MOVE 'F' TO EOF-SW.
RELEASE SORT-REC FROM IN-REC.
RETURN-WRITE.
MOVE SPACES TO EOF-SW.
PERFORM WRITE-FL
UNTIL EOF-SW = 'F'.
PERFORM CLOSE-FILES-RTN.
RETURN-WRITE-RTN-EXIT. EXIT.
WRITE-FL.
RETURN SORT-FILE RECORD INTO OUT-REC
AT END MOVE 'F' TO EOF-SW.
WRITE OUT-REC.
WRITE-FL-RTN-EXIT. EXIT.
CLOSE-FILES-RTN.
CLOSE IN-FILE OUT-FILE.
CLOSE-FILES-RTN-EXIT. EXIT.
我可以编译这个程序,但是当它执行时,它给出了以下错误:
CEE3204S The system detected a protection exception (System Completion
Code=0C4). From compile unit SU98PGM6 at entry point SU98PGM6
at compile unit offset +0005517A at address 1F45517A.
我已经搜索过这个错误,但我无法弄清楚是什么导致我的程序出现这个问题。
我在注意到评论后进行了一些更改,但我仍然遇到与此更改后的代码相同的问题。
READ-RELEASE.
PERFORM OPEN-FILES-RTN.
PERFORM READ-INPUT
UNTIL EOF-SW = 'F'.
READ-RELEASE-RTN-EXIT. EXIT.
READ-INPUT.
READ IN-FILE
AT END MOVE 'F' TO EOF-SW
NOT AT END PERFORM PROCESS-INPUT.
PROCESS-INPUT.
MOVE IN-NAME TO S-NAME.
MOVE IN-ADDRESS TO S-ADDRESS.
MOVE IN-ID TO S-ID.
MOVE IN-CREDITS TO S-CREDITS.
RELEASE SORT-REC.
PROCESS-INPUT-RTN-EXIT. EXIT.
RETURN-WRITE.
MOVE SPACES TO EOF-SW.
PERFORM WRITE-FL
UNTIL EOF-SW = 'F'.
PERFORM CLOSE-FILES-RTN.
RETURN-WRITE-RTN-EXIT. EXIT.
WRITE-FL.
RETURN SORT-FILE RECORD INTO OUT-REC
AT END MOVE 'F' TO EOF-SW
NOT AT END PERFORM PROCESS-OUTPUT.
WRITE-FL-RTN-EXIT. EXIT.
PROCESS-OUTPUT.
MOVE S-NAME TO OUT-NAME.
MOVE S-ADDRESS TO OUT-ADDRESS.
MOVE S-ID TO OUT-ID.
MOVE S-CREDITS TO OUT-CREDITS.
WRITE OUT-REC.
PROCESS-OUTPUT-RTN-EXIT. EXIT.
这是我的 JCL
//******** JOB 1,'*****',NOTIFY=*******
//JOBLIB DD DSN=*******.*******.*******,DISP=SHR
//STEP0 EXEC PGM=SU98PGM6
//IFILE DD DSN=*******.*******.*******.*******(*******),DISP=SHR
//SORTWK DD DSN=*******.*******.*******.*******,DISP=SHR
//OFILE DD DSN=*******.*******.*******.*******,
// DISP=(NEW,CATLG,DELETE),
// DCB=(BLKSIZE=0,LRECL=80,RECFM=FB),
// SPACE=(CYL,(1,1),RLSE),
// UNIT=SYSDA
/*
当使用 COBOL、SORT(DFSORT 或 SyncSORT)和语言环境时,//SYSOUT DD 的输出可能会令人困惑,这可能会给您 run-time 消息,因为它们都默认使用 SYSOUT,并且消息将混杂在一起。
幸运的是,您可以更改默认行为,如此处所示的 DFSORT 和语言环境(在 LE 中有很多方法可以指定选项,最灵活的是 JCL 中的 //CEEOPTS DD
):https://whosebug.com/a/29521423/1927206
COBOL 本身有一个编译器选项,OUTDD。该值默认为 SYSOUT,但您可以指定任何 OUTDD(xxxx)
好的,在看过您的 JCL 以及您对程序中的 DISPLAY 语句如何影响数据的评论后,我成功地进行了部分重现。
我使用 DFSORT,但我不了解你的确切行为,所以我假设你使用 SYNCSORT。
我从我的 JCL 中删除 //SYSOUT DD
后得到的行为是这条消息:
IGZ0026W The SORT-RETURN special register was never referenced, but
the current content indicated the sort or merge operation in program
STOB87 on line number 46 was unsuccessful.
当我将 //SYSOUT 添加回 JCL 时,程序 运行 成功。
当我取出 //SYSOUT 并在 SORT 之前添加一个 DISPLAY 时,程序运行。这是因为如果 JCL 中没有 //SYSOUT,则执行的第一个 DISPLAY 将导致动态创建一个(输出将出现在假脱机中,就好像它是一个单独的 JOB,具有相同的名称和作业编号)。
在我的例子中,DFSORT 抱怨缺少 //SYSOUT。使用 DISPLAY,在 DFSORT 启动时不会丢失 //SYSOUT。
我不得不假设 SYNCSORT 面临着类似的问题,但 run-time COBOL 消息并未生成,并且 SYNCSORT 本身在下一个版本中失败。
虽然这看起来是一个简单而常见的问题,但因为我们总是复制一段JCL来制作一段新的JCL,//SYSOUT总是在那里。
请参阅《企业 COBOL 编程指南》第 12 章,了解如何使用 SORT-RETURN 确认 SORT 已成功完成。
我敢肯定,如果您在 JCL 中包含 //SYSOUT,则无论您是否有 DISPLAY,都不会再出现异常终止。
高 "offset" 的原因是异常终止处理器无法识别您的 SORT 产品的 entry-point ,因此不断向后搜索以找到它可以识别的东西,并定位到您的程序entry-point 然后计算出不正确的偏移量。调用某些汇编程序时也会发生这种情况。
首先,对于您的 S0C4,这是一个保护异常,这意味着您正在尝试访问 "belong" 您无法访问的存储。
您在程序 SU98PGM6 中获得了 S0C4。您在此处发帖时狡猾地删除了您的 PROGRAM-ID
姓名,这可能没有帮助。
SU98PGM6 不是您的程序。异常结束(异常结束)位于失败程序中的偏移 X'0005517A' 处。这意味着,从程序的 "start"(入口点)开始,offset/displacement X'0005517A' 处的指令是试图做坏事的指令。该偏移量(十进制形式为 348538)表示一个相当大的程序。你的程序很小。
这可以通过多种方式实现。例如,您可能从其他地方复制了 JCL,但未能更改 EXEC PGM=
。您可能有一个与 STEPLIB
串联中较早的程序同名的程序。您可能编译了错误的程序。等等
当您遇到异常终止时,请始终确认您拥有的编译列表是针对异常终止的程序的。一个简单而有用的方法是:
01 W-WHEN-COMPILED PIC X(8)BX(8).
...
* where it can only be executed once:
MOVE WHEN-COMPILED TO W-WHEN-COMPILED
DISPLAY
"yourname COMPILED ON "
W-WHEN-COMPILED
"yourname" 您替换为 PROGRAM-ID.
之后的文本
输出将是这样的:
yourname COMPILED ON 11/24/15 10.35.26
这将匹配编译列表每页标题中的 date/time。
如果你 运行 一个程序但没有得到那个输出,或者你得到了输出但它不是预期的输出,那么你知道 你的 程序是不是那个 运行ning.
现在开始你的程序。
- 您无需使用 input/output 程序即可进行排序
- 你应该总是使用SELECT语句的FILE STATUS子句,并且总是检查file-status 您定义的字段(每个文件一个),在每个 IO 操作之后。测试输入文件的 file-status 字段将允许您识别 end-of-file 而无需曲折的
AT END/NOT AT END
构造
- 如果您使用排序过程,COBOL 会执行 IO。如果您不这样做,并使用编译器选项 FASTSRT,您的 SORT 产品将执行 IO,这将比 COBOL 更有效。
- 除非您正在选择或重新格式化记录,否则不需要排序过程
- 由于您使用的是对记录进行隐式移动的 INTO,因此您不需要单独移动数据
- COBOL,因为支持 1985 标准的编译器具有 "scope terminators",我很确定您将拥有该标准。在此之前唯一的 scope-terminator 是 full-stop/period。如今,在使用 "imperative statements" 时以及所有条件语句中,都使用明确的、具体的 scope-terminator。在您的情况下,替换使用 READ/END-READ、RETURN/END-RETURN
- 只在
PROCEDURE DIVISION
需要的地方使用 full-stops/periods,而不是在代码行上。这有助于 moving/copying 代码从一个位置到另一个位置
- 使用 88 级 condition-names 进行测试,而不是文字。您可以使名称完全有意义,因此没有人会想知道 'F' 在特定上下文中的含义
要在 COBOL 程序中对文件进行简单排序,请查看 SORT ... USING ... GIVING...
并使用编译器选项 FASTSRT(如果可能)。
您还没有意识到段落(或 SECTION)和 EXIT 语句的含义。
当使用 PERFORM
或 SORT PROCEDURE
执行时转移到段落中的代码,returns 控制何时到达下一段。
您编写的 "exit" 段落从未被使用过,但是查看代码的人会假设(如果他们很傻,很多人会做出这样的假设)您使用了 THRU
并且他们会留在 GO TO
"exit" 段落中。然后他们会惊讶于该程序表现不佳(如果他们幸运的话)并且最终会发现他们已经使用 GO TO 将控制转移到 PERFORM/PROCEDURE.
的范围之外。
如果您当地的标准强制使用 exit-paragraphs,那么您必须在 PERFORM 和 PROCEDURE 语句中使用 THRU。
Exit-paragraphs 完全没用,除了为 GO TO 提供 target-label 之外什么都不做,这意味着将来有人可能会使用 GO TO 为 "convenience"。 =28=]
这是删除了 exit-paragraphs 的原始程序:
IDENTIFICATION DIVISION.
PROGRAM-ID. ******.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT IN-FILE ASSIGN TO IFILE.
SELECT OUT-FILE ASSIGN TO OFILE.
SELECT SORT-FILE ASSIGN TO SORTWK.
DATA DIVISION.
FILE SECTION.
SD SORT-FILE.
01 SORT-REC.
05 S-NAME PIC X(20).
05 S-ADDRESS PIC X(20).
05 S-ID PIC 9(9).
05 S-CREDITS PIC 99.
05 FILLER PIC X(29).
FD IN-FILE.
01 IN-REC.
05 IN-NAME PIC X(20).
05 IN-ADDRESS PIC X(20).
05 IN-ID PIC 9(9).
05 IN-CREDITS PIC 99.
05 FILLER PIC X(29).
FD OUT-FILE.
01 OUT-REC PIC X(80).
WORKING-STORAGE SECTION.
01 WS-WORK-AREA.
05 EOF-SW PIC X VALUE SPACES.
01 WS-DETAIL-LINES.
05 RPT-LINE.
10 OUT-NAME PIC X(20).
10 OUT-ADDRESS PIC X(20).
10 OUT-ID PIC 9(9).
10 OUT-CREDITS PIC 99.
10 FILLER PIC X(29) VALUE SPACES.
PROCEDURE DIVISION.
SORT SORT-FILE
ON ASCENDING KEY S-ID
INPUT PROCEDURE READ-RELEASE
OUTPUT PROCEDURE RETURN-WRITE
GOBACK
.
OPEN-FILES-RTN.
OPEN INPUT IN-FILE
OPEN OUTPUT OUT-FILE
.
READ-RELEASE.
PERFORM OPEN-FILES-RTN
PERFORM READ-INPUT
UNTIL EOF-SW = 'F'
.
READ-INPUT.
READ IN-FILE
AT END MOVE 'F' TO EOF-SW
END-READ
RELEASE SORT-REC FROM IN-REC
.
RETURN-WRITE.
MOVE SPACES TO EOF-SW
PERFORM WRITE-FL
UNTIL EOF-SW = 'F'
PERFORM CLOSE-FILES-RTN
.
WRITE-FL.
RETURN SORT-FILE RECORD INTO OUT-REC
AT END MOVE 'F' TO EOF-SW
END-RETURN
WRITE OUT-REC
.
CLOSE-FILES-RTN.
CLOSE IN-FILE OUT-FILE
.
我还将 STOP RUN
更改为更灵活的 GOBACK,并删除了您的第一个 paragraph-name,因为它是不必要的并且对于 COBOL 新手来说意味着太多(COBOL本身没有 "main" 的概念,因为它可能与您可能知道的其他语言相关。
我正在尝试使用 COBOL 的排序功能。
IDENTIFICATION DIVISION.
PROGRAM-ID. ******.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT IN-FILE ASSIGN TO IFILE.
SELECT OUT-FILE ASSIGN TO OFILE.
SELECT SORT-FILE ASSIGN TO SORTWK.
DATA DIVISION.
FILE SECTION.
SD SORT-FILE.
01 SORT-REC.
05 S-NAME PIC X(20).
05 S-ADDRESS PIC X(20).
05 S-ID PIC 9(9).
05 S-CREDITS PIC 99.
05 FILLER PIC X(29).
FD IN-FILE.
01 IN-REC.
05 IN-NAME PIC X(20).
05 IN-ADDRESS PIC X(20).
05 IN-ID PIC 9(9).
05 IN-CREDITS PIC 99.
05 FILLER PIC X(29).
FD OUT-FILE.
01 OUT-REC PIC X(80).
WORKING-STORAGE SECTION.
01 WS-WORK-AREA.
05 EOF-SW PIC X VALUE SPACES.
01 WS-DETAIL-LINES.
05 RPT-LINE.
10 OUT-NAME PIC X(20).
10 OUT-ADDRESS PIC X(20).
10 OUT-ID PIC 9(9).
10 OUT-CREDITS PIC 99.
10 FILLER PIC X(29) VALUE SPACES.
PROCEDURE DIVISION.
MAIN-RTN.
SORT SORT-FILE
ON ASCENDING KEY S-ID
INPUT PROCEDURE READ-RELEASE
OUTPUT PROCEDURE RETURN-WRITE.
STOP RUN.
OPEN-FILES-RTN.
OPEN INPUT IN-FILE.
OPEN OUTPUT OUT-FILE.
OPEN-FILES-RTN-EXIT. EXIT.
READ-RELEASE.
PERFORM OPEN-FILES-RTN.
PERFORM READ-INPUT
UNTIL EOF-SW = 'F'.
READ-RELEASE-RTN-EXIT. EXIT.
READ-INPUT.
READ IN-FILE
AT END MOVE 'F' TO EOF-SW.
RELEASE SORT-REC FROM IN-REC.
RETURN-WRITE.
MOVE SPACES TO EOF-SW.
PERFORM WRITE-FL
UNTIL EOF-SW = 'F'.
PERFORM CLOSE-FILES-RTN.
RETURN-WRITE-RTN-EXIT. EXIT.
WRITE-FL.
RETURN SORT-FILE RECORD INTO OUT-REC
AT END MOVE 'F' TO EOF-SW.
WRITE OUT-REC.
WRITE-FL-RTN-EXIT. EXIT.
CLOSE-FILES-RTN.
CLOSE IN-FILE OUT-FILE.
CLOSE-FILES-RTN-EXIT. EXIT.
我可以编译这个程序,但是当它执行时,它给出了以下错误:
CEE3204S The system detected a protection exception (System Completion Code=0C4). From compile unit SU98PGM6 at entry point SU98PGM6 at compile unit offset +0005517A at address 1F45517A.
我已经搜索过这个错误,但我无法弄清楚是什么导致我的程序出现这个问题。
我在注意到评论后进行了一些更改,但我仍然遇到与此更改后的代码相同的问题。
READ-RELEASE.
PERFORM OPEN-FILES-RTN.
PERFORM READ-INPUT
UNTIL EOF-SW = 'F'.
READ-RELEASE-RTN-EXIT. EXIT.
READ-INPUT.
READ IN-FILE
AT END MOVE 'F' TO EOF-SW
NOT AT END PERFORM PROCESS-INPUT.
PROCESS-INPUT.
MOVE IN-NAME TO S-NAME.
MOVE IN-ADDRESS TO S-ADDRESS.
MOVE IN-ID TO S-ID.
MOVE IN-CREDITS TO S-CREDITS.
RELEASE SORT-REC.
PROCESS-INPUT-RTN-EXIT. EXIT.
RETURN-WRITE.
MOVE SPACES TO EOF-SW.
PERFORM WRITE-FL
UNTIL EOF-SW = 'F'.
PERFORM CLOSE-FILES-RTN.
RETURN-WRITE-RTN-EXIT. EXIT.
WRITE-FL.
RETURN SORT-FILE RECORD INTO OUT-REC
AT END MOVE 'F' TO EOF-SW
NOT AT END PERFORM PROCESS-OUTPUT.
WRITE-FL-RTN-EXIT. EXIT.
PROCESS-OUTPUT.
MOVE S-NAME TO OUT-NAME.
MOVE S-ADDRESS TO OUT-ADDRESS.
MOVE S-ID TO OUT-ID.
MOVE S-CREDITS TO OUT-CREDITS.
WRITE OUT-REC.
PROCESS-OUTPUT-RTN-EXIT. EXIT.
这是我的 JCL
//******** JOB 1,'*****',NOTIFY=*******
//JOBLIB DD DSN=*******.*******.*******,DISP=SHR
//STEP0 EXEC PGM=SU98PGM6
//IFILE DD DSN=*******.*******.*******.*******(*******),DISP=SHR
//SORTWK DD DSN=*******.*******.*******.*******,DISP=SHR
//OFILE DD DSN=*******.*******.*******.*******,
// DISP=(NEW,CATLG,DELETE),
// DCB=(BLKSIZE=0,LRECL=80,RECFM=FB),
// SPACE=(CYL,(1,1),RLSE),
// UNIT=SYSDA
/*
当使用 COBOL、SORT(DFSORT 或 SyncSORT)和语言环境时,//SYSOUT DD 的输出可能会令人困惑,这可能会给您 run-time 消息,因为它们都默认使用 SYSOUT,并且消息将混杂在一起。
幸运的是,您可以更改默认行为,如此处所示的 DFSORT 和语言环境(在 LE 中有很多方法可以指定选项,最灵活的是 JCL 中的 //CEEOPTS DD
):https://whosebug.com/a/29521423/1927206
COBOL 本身有一个编译器选项,OUTDD。该值默认为 SYSOUT,但您可以指定任何 OUTDD(xxxx)
好的,在看过您的 JCL 以及您对程序中的 DISPLAY 语句如何影响数据的评论后,我成功地进行了部分重现。
我使用 DFSORT,但我不了解你的确切行为,所以我假设你使用 SYNCSORT。
我从我的 JCL 中删除 //SYSOUT DD
后得到的行为是这条消息:
IGZ0026W The SORT-RETURN special register was never referenced, but the current content indicated the sort or merge operation in program STOB87 on line number 46 was unsuccessful.
当我将 //SYSOUT 添加回 JCL 时,程序 运行 成功。
当我取出 //SYSOUT 并在 SORT 之前添加一个 DISPLAY 时,程序运行。这是因为如果 JCL 中没有 //SYSOUT,则执行的第一个 DISPLAY 将导致动态创建一个(输出将出现在假脱机中,就好像它是一个单独的 JOB,具有相同的名称和作业编号)。
在我的例子中,DFSORT 抱怨缺少 //SYSOUT。使用 DISPLAY,在 DFSORT 启动时不会丢失 //SYSOUT。
我不得不假设 SYNCSORT 面临着类似的问题,但 run-time COBOL 消息并未生成,并且 SYNCSORT 本身在下一个版本中失败。
虽然这看起来是一个简单而常见的问题,但因为我们总是复制一段JCL来制作一段新的JCL,//SYSOUT总是在那里。
请参阅《企业 COBOL 编程指南》第 12 章,了解如何使用 SORT-RETURN 确认 SORT 已成功完成。
我敢肯定,如果您在 JCL 中包含 //SYSOUT,则无论您是否有 DISPLAY,都不会再出现异常终止。
高 "offset" 的原因是异常终止处理器无法识别您的 SORT 产品的 entry-point ,因此不断向后搜索以找到它可以识别的东西,并定位到您的程序entry-point 然后计算出不正确的偏移量。调用某些汇编程序时也会发生这种情况。
首先,对于您的 S0C4,这是一个保护异常,这意味着您正在尝试访问 "belong" 您无法访问的存储。
您在程序 SU98PGM6 中获得了 S0C4。您在此处发帖时狡猾地删除了您的 PROGRAM-ID
姓名,这可能没有帮助。
SU98PGM6 不是您的程序。异常结束(异常结束)位于失败程序中的偏移 X'0005517A' 处。这意味着,从程序的 "start"(入口点)开始,offset/displacement X'0005517A' 处的指令是试图做坏事的指令。该偏移量(十进制形式为 348538)表示一个相当大的程序。你的程序很小。
这可以通过多种方式实现。例如,您可能从其他地方复制了 JCL,但未能更改 EXEC PGM=
。您可能有一个与 STEPLIB
串联中较早的程序同名的程序。您可能编译了错误的程序。等等
当您遇到异常终止时,请始终确认您拥有的编译列表是针对异常终止的程序的。一个简单而有用的方法是:
01 W-WHEN-COMPILED PIC X(8)BX(8).
...
* where it can only be executed once:
MOVE WHEN-COMPILED TO W-WHEN-COMPILED
DISPLAY
"yourname COMPILED ON "
W-WHEN-COMPILED
"yourname" 您替换为 PROGRAM-ID.
之后的文本输出将是这样的:
yourname COMPILED ON 11/24/15 10.35.26
这将匹配编译列表每页标题中的 date/time。
如果你 运行 一个程序但没有得到那个输出,或者你得到了输出但它不是预期的输出,那么你知道 你的 程序是不是那个 运行ning.
现在开始你的程序。
- 您无需使用 input/output 程序即可进行排序
- 你应该总是使用SELECT语句的FILE STATUS子句,并且总是检查file-status 您定义的字段(每个文件一个),在每个 IO 操作之后。测试输入文件的 file-status 字段将允许您识别 end-of-file 而无需曲折的
AT END/NOT AT END
构造 - 如果您使用排序过程,COBOL 会执行 IO。如果您不这样做,并使用编译器选项 FASTSRT,您的 SORT 产品将执行 IO,这将比 COBOL 更有效。
- 除非您正在选择或重新格式化记录,否则不需要排序过程
- 由于您使用的是对记录进行隐式移动的 INTO,因此您不需要单独移动数据
- COBOL,因为支持 1985 标准的编译器具有 "scope terminators",我很确定您将拥有该标准。在此之前唯一的 scope-terminator 是 full-stop/period。如今,在使用 "imperative statements" 时以及所有条件语句中,都使用明确的、具体的 scope-terminator。在您的情况下,替换使用 READ/END-READ、RETURN/END-RETURN
- 只在
PROCEDURE DIVISION
需要的地方使用 full-stops/periods,而不是在代码行上。这有助于 moving/copying 代码从一个位置到另一个位置 - 使用 88 级 condition-names 进行测试,而不是文字。您可以使名称完全有意义,因此没有人会想知道 'F' 在特定上下文中的含义
要在 COBOL 程序中对文件进行简单排序,请查看 SORT ... USING ... GIVING...
并使用编译器选项 FASTSRT(如果可能)。
您还没有意识到段落(或 SECTION)和 EXIT 语句的含义。
当使用 PERFORM
或 SORT PROCEDURE
执行时转移到段落中的代码,returns 控制何时到达下一段。
您编写的 "exit" 段落从未被使用过,但是查看代码的人会假设(如果他们很傻,很多人会做出这样的假设)您使用了 THRU
并且他们会留在 GO TO
"exit" 段落中。然后他们会惊讶于该程序表现不佳(如果他们幸运的话)并且最终会发现他们已经使用 GO TO 将控制转移到 PERFORM/PROCEDURE.
如果您当地的标准强制使用 exit-paragraphs,那么您必须在 PERFORM 和 PROCEDURE 语句中使用 THRU。
Exit-paragraphs 完全没用,除了为 GO TO 提供 target-label 之外什么都不做,这意味着将来有人可能会使用 GO TO 为 "convenience"。 =28=]
这是删除了 exit-paragraphs 的原始程序:
IDENTIFICATION DIVISION.
PROGRAM-ID. ******.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT IN-FILE ASSIGN TO IFILE.
SELECT OUT-FILE ASSIGN TO OFILE.
SELECT SORT-FILE ASSIGN TO SORTWK.
DATA DIVISION.
FILE SECTION.
SD SORT-FILE.
01 SORT-REC.
05 S-NAME PIC X(20).
05 S-ADDRESS PIC X(20).
05 S-ID PIC 9(9).
05 S-CREDITS PIC 99.
05 FILLER PIC X(29).
FD IN-FILE.
01 IN-REC.
05 IN-NAME PIC X(20).
05 IN-ADDRESS PIC X(20).
05 IN-ID PIC 9(9).
05 IN-CREDITS PIC 99.
05 FILLER PIC X(29).
FD OUT-FILE.
01 OUT-REC PIC X(80).
WORKING-STORAGE SECTION.
01 WS-WORK-AREA.
05 EOF-SW PIC X VALUE SPACES.
01 WS-DETAIL-LINES.
05 RPT-LINE.
10 OUT-NAME PIC X(20).
10 OUT-ADDRESS PIC X(20).
10 OUT-ID PIC 9(9).
10 OUT-CREDITS PIC 99.
10 FILLER PIC X(29) VALUE SPACES.
PROCEDURE DIVISION.
SORT SORT-FILE
ON ASCENDING KEY S-ID
INPUT PROCEDURE READ-RELEASE
OUTPUT PROCEDURE RETURN-WRITE
GOBACK
.
OPEN-FILES-RTN.
OPEN INPUT IN-FILE
OPEN OUTPUT OUT-FILE
.
READ-RELEASE.
PERFORM OPEN-FILES-RTN
PERFORM READ-INPUT
UNTIL EOF-SW = 'F'
.
READ-INPUT.
READ IN-FILE
AT END MOVE 'F' TO EOF-SW
END-READ
RELEASE SORT-REC FROM IN-REC
.
RETURN-WRITE.
MOVE SPACES TO EOF-SW
PERFORM WRITE-FL
UNTIL EOF-SW = 'F'
PERFORM CLOSE-FILES-RTN
.
WRITE-FL.
RETURN SORT-FILE RECORD INTO OUT-REC
AT END MOVE 'F' TO EOF-SW
END-RETURN
WRITE OUT-REC
.
CLOSE-FILES-RTN.
CLOSE IN-FILE OUT-FILE
.
我还将 STOP RUN
更改为更灵活的 GOBACK,并删除了您的第一个 paragraph-name,因为它是不必要的并且对于 COBOL 新手来说意味着太多(COBOL本身没有 "main" 的概念,因为它可能与您可能知道的其他语言相关。