Allokierte Variablen
Themenpunkte:
Keine direkte Adressierung verwenden
Für allokierte Variablen sollte keine direkte Adressierung verwendet werden. Statt einer direkten Adressierung wird die Verwendung der automatischen Adressierung mit Hilfe des Platzhalters * empfohlen. Mit dem Platzhalter * (%I*, %Q* bzw. %M*) wird eine flexible und optimierte Adressierung von TwinCAT automatisch durchgeführt.
Im Implementierungsteil sollten ebenfalls keine direkten Adresszugriffe stattfinden.
Static Analysis:
Überprüfen mit Hilfe von folgenden Static Analysis Regeln:
Thematisch empfohlene Static Analysis Regel:
Negatives Beispiel:
VAR
bInputSignal AT%IX4.0 : BOOL;
bVar : BOOL;
END_VAR
bVar := %IX0.0;
Positives Beispiel:
VAR
bInputSignal AT%I* : BOOL;
END_VAR
Mehrfache Schreibzugriffe auf Ausgänge vermeiden
Mehrfache Schreibzugriffe auf Ausgänge sollten vermieden werden. Ein mehrfacher Schreibzugriff auf Ausgänge tritt auf, wenn Ausgänge an mehr als einer Stelle im Programm geschrieben werden.
Ausnahme dieser Regel ist, wenn die Zuweisungen in verschiedenen Zweigen einer IF- bzw. CASE-Anweisung durchgeführt werden.
Static Analysis:
Überprüfen mit Hilfe von Static Analysis Regel:
Die Regel SA0004 ist auch in der lizenzfreien Variante Static Analysis Light enthalten.
Negatives Beispiel:
PROGRAM Sample_neg
VAR
bErrorLed AT%Q* : BOOL; // Machine's error LED
bErrorDrill : BOOL; // Drill error status
bErrorTransport : BOOL; // Transport error status
nTestCounter : WORD; // Simple counter
END_VAR
--------------------------------------------------------------------
bErrorLed := bErrorDrill OR bErrorTransport; // NON COMPLIANT: bErrorLed will be written more than once: See action CounterInc
CounterInc();
--------------------------------------------------------------------
--------------------------------------------------------------------
(* --- Method: CounterInc ---
This method increments the counter and checks if nCounterValue is equal to 0 *)
bErrorLed := (nTestCounter = 0); // NON COMPLIANT: bErrorLed will be written more than once: See program MAIN
nTestCounter := nTestCounter + 1;
Positives Beispiel:
PROGRAM Sample_pos
VAR
bErrorLed AT%Q* : BOOL; // Machine's error LED
bErrorDrill : BOOL; // Drill error status
bErrorTransport : BOOL; // Transport error status
bErrorCounter : BOOL; // Test counter error status
nTestCounter : WORD; // Simple counter
END_VAR
--------------------------------------------------------------------
CounterInc();
bErrorLed := bErrorDrill // COMPLIANT
OR bErrorTransport
OR bErrorCounter;
--------------------------------------------------------------------
--------------------------------------------------------------------
(* --- Method: CounterInc ---
This method increments the counter and checks if nCounterValue is equal to 0 *)
bErrorCounter := (nTestCounter = 0); // COMPLIANT
nTestCounter := nTestCounter + 1;
Überlappende Speicherbereiche von Adressvariablen vermeiden
Überlappende Speicherbereiche von Adressvariablen sollten vermieden werden. Überlappende Speicherbereiche treten auf, wenn derselbe Speicherplatz von mehreren Variablen belegt wird.
Wenn ein überlappender Speicherbereich programmtechnisch benötigt wird, können hierfür UNIONs als gezieltes Stilmittel genutzt werden. Überlappende Speicherbereiche von anderen Variablen, z. B. von Adressvariablen, sollten hingegen vermieden werden.
Static Analysis:
Überprüfen mit Hilfe von Static Analysis Regel:
Die Regel SA0028 ist auch in der lizenzfreien Variante Static Analysis Light enthalten.
Negatives Beispiel:
PROGRAM Sample_neg
VAR
nTestWord AT%MW2 : WORD; // Test WORD
nTestLowByte AT%MB4 : BYTE; // NON COMPLIANT: overlaps with nTestWord
nTestHighByte AT%MB5 : BYTE; // NON COMPLIANT: overlaps with nTestWord
END_VAR
--------------------------------------------------------------------
nTestLowByte := 0; // NON COMPLIANT: writes nTestWord = 16#xx00
nTestHighByte := 0; // NON COMPLIANT: writes nTestWord = 16#00xx
nTestWord := 16#C0FF; // Writes nTestLowByte and nTestHighByte too
Positives Beispiel:
// Structure for the positive sample
TYPE ST_2_BYTES :
STRUCT
nLow : BYTE; // Low byte
nHigh : BYTE; // High byte
END_STRUCT
END_TYPE
// Union for the positive sample
TYPE U_BYTE_WORD :
UNION
stLowHigh : ST_2_BYTES; // Struct with two bytes
nValue : WORD; // Test WORD to be united with the two-byte-struct
END_UNION
END_TYPE
PROGRAM Sample_pos
VAR
uTestWordToBytes AT%MW2 : U_BYTE_WORD; // Test union
nTestLowByte : BYTE; // COMPLIANT: not addressed
nTestHighByte : BYTE; // COMPLIANT: not addressed
END_VAR
--------------------------------------------------------------------
uTestWordToBytes.nValue := 16#C0FF; // A test value
nTestLowByte := uTestWordToBytes.stLowHigh.nLow; // Will be 16#FF
nTestHighByte := uTestWordToBytes.stLowHigh.nHigh; // Will be 16#C0
Siehe auch: