__NEW
The operator is an extension of the IEC 61131-3 standard.
The __NEW operator dynamically reserves memory for function blocks to instantiate user-defined data types or arrays of standard data types. The operator returns a suitable typed pointer.
Syntax:
<pointer name> := __NEW( <type> ( , <size> )? );
__DELETE( <pointer name> );
<type> : <function block> | <data unit type> | <standard data type>
// (...)? : Optional
Sample:
pScalarType := __NEW(ScalarType, length);
The __NEW operator creates an instance of the <type> type and returns a pointer to this instance. Then, the initialization of the instance is called. If <type> is a standard scalar data type, the optional operand <size> is also evaluated. In this case the operator generates an array of type <standard data type> and length <size> (number of elements). If the memory allocation attempt fails, __NEW returns the value 0.
Use the __NEW operator within an assignment (":="), otherwise an error message will be issued.
Requirement/consequences:
A function block (FB) or user-defined data type (DUT) whose instance is created dynamically with __NEW occupies a fixed memory area. This requires that you mark the objects with the pragma {attribute 'enable_dynamic_creation'}. This is not necessary for FBs/DUTs that are part of a library.
![]() | No type change is possible via online change If you change the data layout of an FB/DUT in online mode that is marked with the 'enable_dynamic_creation' attribute, you cannot then log in with online change. The reason for this is that the memory area of the object instance has become invalid. The data layout changes when new variables are added to the FB/DUT, existing variables are deleted or the data types of variables are changed. In this case, you can log in with download. |
Router memory:
Dynamic memory is allocated from the router memory pool.
![]() | Status information of the TwinCAT router The function block FB_GetRouterStatusInfo from the Tc2_Utilities library can be used to read status information of the TwinCAT router, such as the available router memory, from the PLC. |
Release the memory:
A dynamic memory reserved with __NEW must be explicitly released using __DELETE. This must be done either already in the same task cycle or at the latest before the PLC is shut down. Otherwise, a so-called memory leak may occur. As a result, other program parts can no longer reserve memory, which can lead to an unstable system. It is recommended to use the PLC library Tc3_DynamicMemory to simplify the handling with dynamic memory.
Allocating a STRING variable:
If you wish to allocate a STRING of the length cLength, use BYTE instead of STRING as the data type.
VAR CONSTANT
cLength : UINT := 150;
END_VAR
VAR
bNew : BOOL := TRUE;
pString : POINTER TO STRING(cLength);
bDelete : BOOL;
END_VAR
IF bNew AND (pSTRING = 0) THEN
pString := __NEW(BYTE, cLength);
bNew := FALSE;
END_IF
IF bDelete THEN
__DELETE(pSTRING);
bDelete := FALSE;
END_IF
Sample with structure:
Structure ST_sample:
{attribute 'enable_dynamic_creation'}
TYPE ST_Sample :
STRUCT
a,b,c,d,e,f : INT;
END_STRUCT
END_TYPE
MAIN program:
PROGRAM MAIN
VAR
pDut : POINTER TO ST_Sample;
bNew : BOOL := TRUE;
bDelete : BOOL;
END_VAR
IF bNew AND (pDut = 0) THEN
pDut := __NEW(ST_Sample);
bNew := FALSE;
END_IF
IF bDelete THEN
__DELETE(pDut);
bDelete := FALSE;
END_IF
Sample with function block:
Function block FB_Dynamic:
{attribute 'enable_dynamic_creation'}
FUNCTION_BLOCK FB_Dynamic
VAR
nCounts : INT;
END_VAR
Method Increase:
METHOD Increase : INT
VAR_INPUT
nCountStep : INT;
END_VAR
nCounts := nCounts + nCountStep;
Increase := nCounts;
MAIN program:
PROGRAM MAIN
VAR
pFB : POINTER TO FB_Dynamic;
nResult : INT;
nIncrease : INT := 5;
bNew : BOOL := TRUE;
bDelete : BOOL;
END_VAR
IF bNew AND (pFB = 0) THEN
pFB := __NEW(FB_Dynamic);
bNew := FALSE;
END_IF
IF (pFB <> 0) THEN
nResult := pFB^.Increase(nCountStep := nIncrease);
END_IF
IF bDelete THEN
__DELETE(pFB);
bDelete := FALSE;
END_IF
Sample with array:
MAIN program:
PROGRAM MAIN
VAR
bNew : BOOL := TRUE;
bDelete : BOOL;
pArrayBytes : POINTER TO BYTE;
nTest : INT;
END_VAR
IF bNew AND (pArrayBytes = 0) THEN
pArrayBytes := __NEW(BYTE, 25);
bNew := FALSE;
END_IF
IF (pArrayBytes <> 0)THEN
pArrayBytes[24] := 125; // writing a value to the last array element
nTest := pArrayBytes[24];
END_IF
IF bDelete THEN
__DELETE(pArrayBytes);
bDelete := FALSE;
END_IF