POU: CheckBounds
Die Aufgabe dieser Überwachungsfunktion ist eine angemessene Behandlung von Verletzungen von Feldgrenzen. Eine Reaktion auf eine Verletzung kann beispielsweise das Setzen eines Error-Flags oder das Verändern des Arrayindex sein. Die Prüfung erfolgt nur bei einem variablen Feldindex. Ein fehlerhafter konstanter Arrayindex führt zu einem Compilerfehler. Die Funktion wird implizit aufgerufen, sobald der ARRAY-Variablen Werte zugewiesen werden.
Für weitere Informationen siehe: Bausteine für implizite Prüfungen verwenden und Bausteine für implizite Prüfungen verwenden
Nach dem Einfügen der Funktion erhalten Sie automatisch erzeugten Code in Deklarationsteil und Implementierungsteil. Siehe unten.
Achtung
Um die Funktionalität der Überwachungsfunktionen zu erhalten, dürfen Sie den Deklarationsteil nicht verändern. Als einzige Ausnahme dürfen Sie lokale Variablen hinzufügen.
Deklarationsteil:
Automatisch erzeugter Code: Nicht editieren!
FUNCTION CheckBounds : DINT
VAR_INPUT
index, lower, upper: DINT;
END_VARImplementierung:
Automatisch erzeugter Code: Es handelt sich hierbei um einen Implementierungsvorschlag.
IF index < lower THEN
CheckBounds := lower;
ELSIF index > upper THEN
CheckBounds := upper;
ELSE
CheckBounds := index;
END_IFDeklaration:
Sie können auch einen Haltepunkt setzen, Meldungen protokollieren oder beispielsweise bei einer Exception anhalten. Fügen Sie CmpApp.Library, SysExcept.Library und SysTypes2_Itf hinzu.
(* 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_VARImplementierung:
_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
Beim Aufruf erhält die Funktion CheckBounds folgende Eingangsparameter:
index: Index des Arrayelementslower: Untergrenze des Arraybereichsupper: Obergrenze des Arraybereichs
Rückgabewert ist der Index des Arrayelements, sofern sich dieser im gültigen Bereich befindet. Ansonsten gibt CODESYS je nach Verletzung des Grenzbereichs die Ober- oder Untergrenze zurück.
Beispiel: Arrayzugriff außerhalb der Arraygrenzen
Im unten stehenden Beispielprogramm unterschreitet der Index die definierte Untergrenze des Arrays a.
PROGRAM PLC_PRG
VAR
a: ARRAY[0..7] OF BOOL;
b : INT := 10;
END_VAR
Implementierung
a[b]:=TRUE;
Die Funktion CheckBounds bewirkt in diesem Beispiel, dass der Index 10 in die Obergrenze des Arraybereichs von a abgeändert wird. Damit wird der Wert TRUE dem Element a[7] zugewiesen. Auf diese Weise korrigiert die Funktion Arrayzugriffe außerhalb des gültigen Arraybereichs.
Beispiel: Verletzung von Arraygrenzen
Fügen Sie im Bibliotheksverwalter der Applikation folgende Bibliotheken ein:
CmpApp.libraryundSysExcept.libraryals PlatzhalterbibliothekenSysTypes2_Itfs.librarymit Immer neueste Version
Fügen Sie ein Objekt CheckBounds unter der Applikation ein und ändern Sie den vorgegebenen Code wie folgt:
Deklarationsteil:
FUNCTION CheckBounds : DINT
VAR_INPUT
index, lower, upper: DINT;
END_VAR
VAR
_pApp : POINTER TO CmpApp.APPLICATION;
_Result : ISystypes2.RTS_IEC_RESULT;
END_VARImplementierungsteil:
// 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_IFProgrammieren Sie ein Objekt MAIN_PRG mit dem unten gezeigten Inhalt unter der Applikation.
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;Wenn Sie diese Applikation laden und starten, wird bei Verletzung der Arraygrenzen eine Exception generiert. Die Abarbeitung stoppt in CheckBounds, sodass die Art des Fehlers erkenntlich ist.