Pointer Checks (POU CheckPointer)
Monitoring function CheckPointer for pointers
Use this function to monitor the memory access of pointers during runtime. In contrast to other monitoring functions, there is no default implementation for CheckPointer. You must carry out the implementation yourself!
The purpose of the CheckPointer function is to check whether the transferred pointer points to a valid memory address, and whether the orientation of the referenced memory area matches the type of variable to which the pointer points. If both conditions are met, the pointer itself is returned. Otherwise, the function should perform proper error handling.
![]() | Do not change the declaration part To maintain the functionality of the monitoring functions, the declaration part must not be modified. The only exception is to add local variables. |
![]() | The monitoring function is not called implicitly for the THIS pointer and the SUPER pointer. |
![]() | The function CheckPointer also acts on variables of the type REFERENCE in the same way as on pointer variables. |
Template
Declaration:
// Implicitly generated code : DO NOT EDIT
FUNCTION CheckPointer : POINTER TO BYTE
VAR_INPUT
ptToTest : POINTER TO BYTE;
iSize : DINT;
iGran : DINT;
bWrite : BOOL;
END_VAR
Implementation (incomplete!):
// No standard way of implementation. Fill your own code here
{noflow}
CheckPointer := ptToTest;
{flow}
When the function is called, TwinCAT transfers the following input parameters to it:
- ptToTest: target address of the pointer
- iSize: size of the referenced variable in bytes
- iGran: granularity of the referenced variable in bytes, i.e. the largest non-structured data type contained in the referenced variables.
- bWrite: type of access (TRUE = write access, FALSE = read access)
If the check result is positive, the input pointer is returned unchanged (ptToTest).
Example:
The following implementation example displays a message in the TwinCAT output window as soon as an invalid pointer is recognized. This implementation recognizes various types of invalid pointers. However, it cannot recognize all invalid pointers.
// Implicitly generated code : DO NOT EDIT
FUNCTION CheckPointer : POINTER TO BYTE
VAR_INPUT
ptToTest : POINTER TO BYTE;
iSize : DINT;
iGran : DINT;
bWrite : BOOL;
END_VAR
IF ptToTest=0 THEN
ADSLOGSTR(ADSLOG_MSGTYPE_ERROR OR ADSLOG_MSGTYPE_STRING,'CheckPointer failed due to invalid destination address.','');
ELSIF iSize<=0 THEN
ADSLOGSTR(ADSLOG_MSGTYPE_ERROR OR ADSLOG_MSGTYPE_STRING,'CheckPointer failed due to invalid size.','');
ELSIF iGran<=0 THEN
ADSLOGSTR(ADSLOG_MSGTYPE_ERROR OR ADSLOG_MSGTYPE_STRING,'CheckPointer failed due to invalid granularity.','');
// -> Please note that the following memory area check is time consuming:
//ELSIF F_CheckMemoryArea(pData:=ptToTest,nSize:=DINT_TO_UDINT(iSize)) = E_TcMemoryArea.Unknown THEN
// ADSLOGSTR(ADSLOG_MSGTYPE_ERROR OR ADSLOG_MSGTYPE_STRING,'CheckPointer failed due to unknown memory area.','');
END_IF
CheckPointer := ptToTest;
![]() | Consequence of an invalid pointer The consequence of an invalid pointer is usually that the runtime is stopped as soon as any access takes place via this pointer. The CheckPointer function cannot prevent this in most cases. The purpose of this monitoring function is actually to make efficient cause diagnosis possible. |
Sample: Generation of a core dump at runtime in CheckBounds()
The following is a sample in which the CreateCallstackCoreDump() function is called in the Bound Checks (POU CheckBounds) function for implicit checks.
This allows you to find out in which line of code a possible access outside the valid array bounds occurs without stopping the runtime using a breakpoint.
By calling CreateCallstackCoreDump() within the corresponding IF branches of CheckBounds(), the call stack with the position of the faulty array access is saved in a core dump during runtime and can be loaded at a suitable time for analysis purposes.
Function CheckBounds:
// Implicitly generated code : DO NOT EDIT
FUNCTION CheckBounds : DINT
VAR_INPUT
index, lower, upper: DINT;
END_VAR
// Implicitly generated code: Only an implementation suggestion
{noflow}
IF index < lower THEN
CreateCallstackCoreDump('CheckBounds_IdxTooLow');
CheckBounds := lower;
ELSIF index > upper THEN
CreateCallstackCoreDump('CheckBounds_ IdxTooHigh');
CheckBounds := upper;
ELSE
CheckBounds := index;
END_IF
For example, a core dump with the following name is created:
Port_851_CallStackDump_CheckBounds_IdxTooLow.2322085807.core
See also: