Pointers, references, interfaces
Topics:
Temporary existence of pointers/references/interfaces to temporarily existing objects
Pointers, references or interfaces that refer to temporarily existing objects should only exist as long as the objects themselves.
objects exist temporarily, for example, when instantiated in methods or functions or as VAR_TEMP.
Static Analysis:
Check with the help of Static Analysis rule:
Negative sample:
FUNCTION_BLOCK FB_Sample_neg
VAR
pPointerToSample : POINTER TO ST_Sample; // Sample pointer to a structure
END_VAR
METHOD PUBLIC nccl_TestMethod
VAR
stSample : ST_Sample;
END_VAR
--------------------------------------------------------------------
pPointerToSample := ADR(stSample);
// NON COMPLIANT: stSample is declared in an inner scope. So pPointerToSample points to an invalid object outside of the method.
Positive sample:
FUNCTION_BLOCK FB_Sample_pos
VAR
END_VAR
METHOD PUBLIC nccl_TestMethod
VAR
stSample : ST_Sample;
pPointerToSample : POINTER TO ST_Sample; // COMPLIANT
END_VAR
--------------------------------------------------------------------
pPointerToSample := ADR(stSample);
Reset pointer/references every cycle
You should reset pointers and references every cycle.
An online change can change the addresses of statically declared variables and objects. Therefore, pointers and references pointing to such variables should be reset every cycle. For this purpose, the address of the variable can be queried again using ADR() operator.
Pointers to dynamically created objects (__NEW) may not be reset every cycle, but must remain until the object is explicitly released (__DELETE).
If pointers/references are requested at the input of a method, the mandatory assignment of all method input parameters causes the pointer/references to be reset by the caller.
Negative sample:
FUNCTION_BLOCK FB_Sample_neg
VAR
aBuffer : ARRAY[cMin..cMax] OF BYTE; // Sample buffer
pBuffer : POINTER TO BYTE := ADR(aBuffer); // Sample pointer to buffer
// NON COMPLIANT: the memory address of aBuffer could change during an online change. So pBuffer could become invalid.
END_VAR
Positive sample:
FUNCTION_BLOCK FB_Sample_pos
VAR
aBuffer : ARRAY[cMin..cMax] OF BYTE; // Sample buffer
pBuffer : POINTER TO BYTE; // Sample pointer to buffer
END_VAR
-------------------------------------------------
pBuffer := ADR(aBuffer); // COMPLIANT: pointer is updated before usage in implementation
Check pointers/references/interfaces before each use
Pointers, references and interfaces should be checked for validity before each use. For pointers and interfaces this check is done by querying for "not equal to 0" (<> 0), for references the operator __ISVALIDREF() is used.
For special checks of a pointer, the function F_CheckMemoryArea of the Tc2_System library is available for exceptional situations, which can be used to query the memory area referenced by a pointer.
Within the condition that checks the validity of the pointer, it should not be used at the same time. If you want to implement this, you must use the operator AND_THEN. See sample 2.
Static Analysis:
Verify using the following Static Analysis rules:
- SA0039: Possible null pointer dereferences
- SA0046: Possible use of not initialized interfaces
- SA0145: Possible use of not initialized references
Thematically recommended Static Analysis rules:
General program elements for the following samples:
Function block FB_Sample implements the interface I_Sample:
FUNCTION_BLOCK FB_Sample IMPLEMENTS I_Sample
Sample program:
PROGRAM Sample
VAR
pSample : POINTER TO FB_Sample;
refSample : REFERENCE TO FB_Sample;
ipSample : I_Sample;
END_VAR
Negative sample:
pSample^.DoSomething();
refSample.DoSomething();
ipSample.DoSomething();
Positive sample 1:
IF pSample <> 0 THEN
pSample^.DoSomething();
END_IF
IF __ISVALIDREF(refSample) THEN
refSample.DoSomething();
END_IF
IF ipSample <> 0 THEN
ipSample.DoSomething();
END_IF
Positive sample 2:
IF ipBuffer <> 0 THEN
IF ipBuffer.bAvailable THEN
ipBuffer.Clear();
END_IF
END_IF
IF ipBuffer <> 0 AND_THEN ipBuffer.bAvailable THEN
ipBuffer.Clear();
END_IF
Prefer references over pointers
Prefer references to pointers if possible, since references are more type-safe compared to pointers.
However, in special cases, the use of pointers is required, for example, when pointer arithmetic is needed. Likewise, buffers of arbitrary size are readily passed to a function. Pointers are also used for this purpose.
Static Analysis:
Helpful rules for pointer use that may be required:
See also: