Skip to main content

POU: CheckBounds

The task of this monitoring function is to handle bound violations appropriately. Examples of reactions to violations include setting error flags and changing the value of the array index. The check is performed only for one variable array index. An incorrect constant array index causes a compiler error. The function is implicitly called as soon as the values are assigned to the ARRAY variables.

For more information, see the following: Using POUs for Implicit Checks and Using POUs for Implicit Checks

After inserting the function, you receive automatically generated code in the declaration and implementation parts. See below.

Caution

To get the feature for monitoring functions, do not edit the declaration part. However, you are permitted to add local variables.

Declaration part:

Automatically generated code: Do not edit!

FUNCTION CheckBounds : DINT
VAR_INPUT
      index, lower, upper: DINT;
END_VAR

Implementation:

Automatically generated code: This is a suggested implementation.

IF  index < lower THEN
      CheckBounds := lower;
ELSIF  index > upper THEN
      CheckBounds := upper;
ELSE
      CheckBounds := index;
END_IF

Declaration:

You can also set a breakpoint, log messages, or halt on an exception, for example. Add CmpApp.Library, SysExcept.Library, and SysTypes2_Itf.

(* It is also possible to set a breakpoint, log messages or e.g. to halt on an exception:
Add CmpApp.library, SysExcept.library and SysTypes2_Itf as newest.*)
VAR
    _pApp : POINTER TO CmpApp.APPLICATION;
    _result   : SysTypes.RTS_IEC_RESULT;
END_VAR

Implementation:

_pApp := AppGetCurrent(pResult:=_result);
IF  index < lower THEN
        CheckBounds := lower;
        IF _pApp <> 0 THEN
                AppGenerateException(pApp:=_pApp, ulException:=RtsExceptions.RTSEXCPT_ARRAYBOUNDS);
        END_IF
ELSIF  index > upper THEN
        CheckBounds := upper;
        IF _pApp <> 0 THEN
                AppGenerateException(pApp:=_pApp,   ulException:=RtsExceptions.RTSEXCPT_ARRAYBOUNDS);
        END_IF
ELSE
        CheckBounds := index;
END_IF

When the CheckBounds function is called, it receives the following input parameters:

  • index: Index of the array element

  • lower: Lower limit of the array range

  • upper: Upper limit of the array range

The return value is the index of the array element, as long as it is within a valid range. If not, then the CODESYS returns either the upper or lower limit, depending on which threshold was violated.

Example: Array access outside of the array bounds

Example 541. Correction of the access to an array outside the defined array bounds

In the sample program below, the index falls short of the defined lower limit of the a array.

PROGRAM PLC_PRG
VAR
    a: ARRAY[0..7] OF BOOL;
    b : INT := 10;
END_VAR

Implementation

a[b]:=TRUE;

In this example, the CheckBounds function causes a to change the upper limit of the array range index to 10. The value TRUE is assigned then to the element a[7]. In this way, the function corrects array access outside of the valid array range.



Example: Violation of array bounds

Example 542. Output of an exception when array bounds are violated.

Add the following libraries in the Library Manager of the application:

  • CmpApp.library and SysExcept.library as placeholder libraries

  • SysTypes2_Itfs.library with Newest version always

Add a CheckBounds object below the application and modify the specified code as shown below.

Declaration part:

FUNCTION CheckBounds : DINT
VAR_INPUT
    index, lower, upper: DINT;
END_VAR
VAR
    _pApp : POINTER TO CmpApp.APPLICATION;
    _Result : ISystypes2.RTS_IEC_RESULT;
END_VAR

Implementation part:

// Automatically generated code: This is an implementation suggestion.
_pApp := AppGetCurrent(pResult := _Result);
IF  index < lower THEN
    CheckBounds := lower;
    IF _pApp <> 0 THEN
        AppGenerateException(pApp := _pApp, ulException := RtsExceptions.RTSEXCPT_ARRAYBOUNDS);
    END_IF
ELSIF  index > upper THEN
    CheckBounds := upper;
    IF _pApp <> 0 THEN
       AppGenerateException(pApp:=_pApp,   ulException:=RtsExceptions.RTSEXCPT_ARRAYBOUNDS);
    END_IF
ELSE
    CheckBounds := index;
END_IF

Program a MAIN_PRG object below the application with the contents shown below.

PROGRAM MAIN_PRG
VAR
    xInit : BOOL;
    arData : ARRAY[0..7] OF BYTE;
    i : INT;
    dwAdr : DWORD;
END_VAR
IF NOT xInit THEN
    // Required for CheckBounds
    xInit  := TRUE;
END_IF

// Set i to a value > 7 or < 0
// Generates an exception in CheckBounds, user-defined
arData[i] := 11;

When you load and start this application, an exception will be thrown when array bounds are violated. Processing stops in CheckBounds so that the type of error can be detected.