Use of functions and methods
Topics:
Evaluate returned error information of a POU
If a function, a method or a function block returns error information, always evaluate it.
Static Analysis:
Thematically recommended Static Analysis rules:
Negative sample:
PROGRAM Sample_neg
VAR
fbFileOpen : FB_FileOpen; // FileOpen-FB for logger
bFileOpenExec : BOOL; // Execute FileOpen-FB
END_VAR
// NON COMPLIANT: error information of fbFileOpen will not be used
fbFileOpen(
sPathName := 'C:\TestFile.txt',
nMode := FOPEN_MODEWRITE OR FOPEN_MODETEXT,
ePath := PATH_GENERIC,
bExecute := bFileOpenExec,
tTimeout := T#3S);
Positive sample:
PROGRAM Sample_pos
VAR
fbFileOpen : FB_FileOpen; // FileOpen-FB for logger
bFileOpenExec : BOOL; // Execute FileOpen-FB
bFileOpenError : BOOL; // Error flag of FileOpen-FB
nFileOpenErrorID : UDINT; // Error code of FileOpen-FB
END_VAR
// COMPLIANT: error information will be handled
fbFileOpen(
sPathName := 'C:\TestFile.txt',
nMode := FOPEN_MODEWRITE OR FOPEN_MODETEXT,
ePath := PATH_GENERIC,
bExecute := bFileOpenExec,
tTimeout := T#3S,
bError => bFileOpenError,
nErrId => nFileOpenErrorID);
IF bFileOpenError THEN
F_DoSomethingUsefulHere(); // Handle error here
END_IF
Use return value of a function/method
The return value of a function/method should be used, i.e. queried and evaluated, at the call point of the function/method. This is especially useful if an error value is returned in this way. However, exceptions are also possible where the return value does not have to be used in every call of the function/method.
Static Analysis:
Check with the help of Static Analysis rule:
General program elements for this rule:
(* Function for all samples in this rule: Adds a message to logger system.
Returns TRUE if successful, FALSE on Error. *)
FUNCTION F_AddLogMessage : BOOL
VAR_INPUT
sMessage : WSTRING; // Message to be logged
dtTimestamp : DATE_AND_TIME; // Timestamp of the message
END_VAR
Negative sample:
PROGRAM Sample_neg
VAR
dtNow : DATE_AND_TIME; // Actual system time
END_VAR
// NON COMPLIANT: return value of function will not be used
F_AddLogMessage(sMessage := "Test Message", dtTimestamp := dtNow);
Positive sample:
PROGRAM Sample_pos
VAR
dtNow : DATE_AND_TIME; // Actual system time
bSendMessageOk : BOOL; // Used to check if sending of message was successful
END_VAR
// COMPLIANT: return value of function will be used
bSendMessageOk := F_AddLogMessage(sMessage := "Test Message", dtTimestamp := dtNow);
IF NOT bSendMessageOk THEN
F_DoSomethingUsefulHere(); // Handle error here
END_IF
Do not call functions/methods within themselves
Functions / methods should not call themselves directly or indirectly, in order to avoid recursions. In programming languages other than IEC61131, recursions should also be used advisedly.
Static Analysis:
Check with the help of Static Analysis rule:
Negative sample:
FUNCTION F_Sample_neg : DWORD
VAR_INPUT
nFac : DWORD; // The faculty of this value will be calculated
END_VAR
--------------------------------------------------------------------
IF nFac = 0 THEN
F_Sample_neg := 1;
ELSE
// NON COMPLIANT: implicit recursion. F_Sample_neg_IndirectFac calls F_Sample_neg
F_Sample_neg := nFac * F_Sample_neg_IndirectFac(nFac := (nFac - 1));
END_IF
--------------------------------------------------------------------
--------------------------------------------------------------------
FUNCTION F_Sample_neg_IndirectFac : DWORD
VAR_INPUT
nFac : DWORD; // The faculty of this value will be calculated
END_VAR
--------------------------------------------------------------------
F_Sample_neg_IndirectFac := F_Sample_neg(nFac := nFac);
Positive sample:
FUNCTION F_Sample_pos : DWORD
VAR_INPUT
nFac : DWORD; // The faculty of this value will be calculated
END_VAR
VAR
nTemp : DWORD; // Temporary variable used to calculate faculty
nCount : DWORD; // Counter variable used to calculate faculty
END_VAR
--------------------------------------------------------------------
nTemp := 1;
IF nFac > 0 THEN
FOR nCount := 1 TO nFac DO
nTemp := nTemp * nCount;
END_FOR
END_IF
F_Sample_pos := nTemp;
See also: