1

如果使用另一个表的索引访问表元素(没有索引的表),则可能会在 IBM 主机上出现表溢出错误。但是在使用 GnuCOBOL(以前称为 OpenCOBOL)时,相同的程序不会导致崩溃或消息(即使有调试选项)。

例如

    IDENTIFICATION DIVISION.
    PROGRAM-ID.    TSTPROGX.
    DATA DIVISION.
    WORKING-STORAGE SECTION.
    01  IX                         PIC 9(04) COMP VALUE ZERO.
    01  VARS.
        05  S-PART-C.
            10  S-DETAIL      OCCURS 100 TIMES
                                    INDEXED BY S-SUB.
                15  S-ACTUAL  PIC 9(06) VALUE ZERO.
                15  S-ACTUAL-A
                                    REDEFINES S-ACTUAL
                                    PIC X(06).
                15  S-GRADE   PIC X(02) VALUE LOW-VALUE.
        05  POS-USED-ARRAY          PIC X(999)
                                   VALUE SPACE.
        05  FILLER                  REDEFINES POS-USED-ARRAY
                                              OCCURS 999.
            10  FILLER-X            PIC X .
                88  POSITIONS-USED-X          VALUE 'T'.
    PROCEDURE DIVISION.
        SET S-SUB TO 1
        PERFORM VARYING IX FROM 1 BY 1 UNTIL IX > 999
           SET S-SUB TO IX
           SET POSITIONS-USED-X(S-SUB) TO TRUE
           DISPLAY IX ":" FILLER-X(S-SUB)
        END-PERFORM
        GOBACK.

是否有编译器选项来发出警告以避免这种用法?

通过使用正确的用法可以避免此错误。即,使用变量“IX”,而不是使用不同表的索引(S-SUB)。

SET POSITIONS-USED-X(I-X) TO TRUE

一般来说,交换独立表(不同大小)的索引似乎是错误的。

4

1 回答 1

3

假设主机是指大型机,使用企业 COBOL,我最初包含的链接为您提供了答案。

在 Enterprise COBOL 中,您可以使用一个表中的索引来引用另一个表上的数据,即使是没有索引的表(如您的示例),但除非从属于 OCCURS 的数据长度相同,否则您不会得到你期望的结果。

使用 Enterprise COBOL 和编译器选项 SSRANGE,您问题中的代码将失败(如您所知)。它会在哪里失败?与索引 S-SUB 相关的 OCCURS 的长度是 8 个字节。该长度有效地“内置”到索引 S-SUB 中。将 999(第二个表的长度)除以 8 得到 124(忽略余数),因此将 S-SUB 设置为 124 是可以的,而设置为 125 则不行,因为 125 将从 1,000 开始,而您只有999 字节。

在 GnuCOBOL 中,索引没有内置长度,它是一个简单的整数,与表中的出现直接相关。但是,在达到 100 之后,您开始溢出第一个表(没有编译器/运行时检查)和 125 个引用,之后您超出了第二个表的末尾,并且在您的编译选项中使用 -g 将得到崩溃取决于在 GnuCOBOL 编译器生成的 C 程序中分配存储的方式(和多少)。225 将是可能发生崩溃的第一个点,但它可能不会在那个点发生,它可能会或可能不会在以后发生。

基本上,您无法真正期望代码能够正常工作,您知道,您只想知道如何设置编译器以使用 GnuCOBOL 检查它。目前,你不能。

通常定义一个字段来保存表中的最大条目,另一个定义说明正在使用的条目数。使用条目时,您首先检查表是否已满。

您也可以使用LENGTH OF/FUNCTION LENGTH来防止越过表格的末尾。

您可以将这两种方法结合起来。

您只是没有可以在此处为您提供帮助的 GnuCOBOL 开关。-g归结为C编译器。它给你一些东西,但不是一切,只是取决于。

此外,在我看来,拥有一个用于下标的数据名IX和一个名为 的索引也不是一个好主意S-SUB。这会使程序的人类读者感到困惑。

有关使用来自不同表的索引的一些详细信息,请参阅此答案:https ://stackoverflow.com/a/36254166/1927206。

IBM Enterprise COBOL 可以检查使用索引引用的存储是否在引用元素从属的表中。这是通过编译器选项 SSRANGE 完成的。如果引用了表外的数据(通过任何方式的下标,或通过引用修改),则会生成运行时诊断消息。在除最新的 Enterprise COBOL 编译器之外的所有编译器中,该问题都会导致“异常结束”(“异常结束”)。使用最新的编译器,有一些子选项可以提供更多控制。

这不是严格检查表格的“界限”。对于一维表,表引用检查与边界检查一致。对于多维表,它没有。第二个和后续级别的下标可能是“错误的”,但除非它们引起表外的引用,否则这是没有问题的。

GnuCOBOL/OpenCOBOL 不检查下标的使用或通过下标/引用修改对表的引用。如果您想考虑自己添加它,我们将非常欢迎您。或者您可以将其作为功能请求发布。访问https://sourceforge.net/p/open-cobol/discussion/?source=navbaring,但不是全部。

有关使用来自不同表的索引的一些详细信息,请参阅此答案:https ://stackoverflow.com/a/36254166/1927206。

IBM Enterprise COBOL 可以检查使用索引引用的存储是否在引用元素从属的表中。这是通过编译器选项 SSRANGE 完成的。如果引用了表外的数据(通过任何方式的下标,或通过引用修改),则会生成运行时诊断消息。在除最新的 Enterprise COBOL 编译器之外的所有编译器中,该问题都会导致“异常结束”(“异常结束”)。使用最新的编译器,有一些子选项可以提供更多控制。

这不是严格检查表格的“界限”。对于一维表,表引用检查与边界检查一致。对于多维表,它没有。第二个和后续级别的下标可能是“错误的”,但除非它们引起表外的引用,否则这是没有问题的。

GnuCOBOL/OpenCOBOL 不检查下标的使用或通过下标/引用修改对表的引用。如果您想考虑自己添加它,我们将非常欢迎您。或者您可以将其作为功能请求发布。访问https://sourceforge.net/p/open-cobol/discussion/?source=navbar

于 2016-04-07T16:04:02.993 回答