Pointers, references, interfaces

Topics:

  1. Temporary existence of pointers/references/interfaces to temporarily existing objects [++]
  2. Reset pointer/references every cycle [++]
  3. Check pointers/references/interfaces before each use [++]
  4. Prefer references over pointers [++]

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:

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: