__NEW
Der Operator ist eine Erweiterung der Norm IEC 61131-3.
Der __NEW-Operator reserviert dynamisch Speicher für Funktionsbausteine, um benutzerdefinierte Datentypen oder Arrays von Standarddatentypen zu instanziieren. Der Operator gibt einen passend getypten Pointer zurück.
Syntax:
<pointer name> := __NEW( <type> ( , <size> )? );
__DELETE( <pointer name> );
<type> : <function block> | <data unit type> | <standard data type>
// (...)? : Optional
Beispiel:
pScalarType := __NEW(ScalarType, length);
Der Operator __NEW erzeugt eine Instanz des Typs <type> und gibt einen Pointer auf diese Instanz zurück. Anschließend wird die Initialisierung der Instanz aufgerufen. Wenn es sich bei <type> um einen skalaren Standarddatentyp handelt, wird zusätzlich der optionale Operand <size> ausgewertet. Der Operator erzeugt dann ein Array des Typs <standard data type> der Länge <size> (Elementanzahl). Wenn der Versuch Speicher zu allozieren scheitert, gibt __NEW den Wert 0 zurück.
Verwenden Sie den __NEW-Operator innerhalb einer Zuweisung („:=“), ansonsten wird eine Fehlermeldung ausgegeben.
Voraussetzung/Folgen:
Ein Funktionsbaustein (FB) oder ein benutzerdefinierter Datentyp (DUT), dessen Instanz mit __NEW dynamisch erzeugt wird, belegt einen fixen Speicherbereich. Dafür ist es erforderlich, dass Sie die Objekte mit dem Pragma {attribute 'enable_dynamic_creation'} kennzeichnen. Bei FBs/DUTs, die Teil einer Bibliothek sind, ist dies nicht erforderlich.
![]() | Keine Typänderung per Online-Change möglich Wenn Sie im Onlinebetrieb das Datenlayout eines FBs/DUTs ändern, welcher mit dem Attribut 'enable_dynamic_creation' gekennzeichnet ist, können Sie anschließend kein Einloggen mit Online-Change ausführen. Der Grund hierfür ist, dass der Speicherbereich der Objekt-Instanz ungültig geworden ist. Eine Änderung des Datenlayouts liegt vor, wenn bei dem FB/DUT neue Variablen hinzugefügt, bestehende Variablen gelöscht oder Datentypen von Variablen geändert werden. In diesem Fall können Sie ein Einloggen mit Download ausführen. |
Routerspeicher:
Dynamischer Speicher wird aus dem Routerspeicherpool alloziert.
![]() | Statusinformationen des TwinCAT-Routers Mithilfe des Funktionsbausteins FB_GetRouterStatusInfo aus der Tc2_Utilities-Bibliothek können Sie Statusinformationen des TwinCAT-Routers, wie z. B. den verfügbaren Router-Speicher, aus der SPS auslesen. |
Freigabe des Speichers:
Ein mit __NEW reservierter dynamischer Speicher muss mittels __DELETE explizit freigegeben werden. Dies muss entweder bereits im gleichen Taskzyklus oder spätestens vor dem Herunterfahren der SPS geschehen. Andernfalls kann es zu einem sogenannten Speicherleck (memory leak) kommen. Infolgedessen können andere Programmteile keinen Speicher mehr reservieren, wodurch ein instabiles System entstehen kann. Es wird die Verwendung der SPS-Bibliothek Tc3_DynamicMemory empfohlen, um die Handhabung mit dynamischem Speicher zu vereinfachen.
Allozieren einer STRING-Variablen:
Wenn Sie einen STRING der Länge cLength allozieren möchten, verwenden Sie BYTE anstelle von STRING als Datentyp.
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
Beispiel mit Struktur:
Struktur ST_Sample:
{attribute 'enable_dynamic_creation'}
TYPE ST_Sample :
STRUCT
a,b,c,d,e,f : INT;
END_STRUCT
END_TYPE
Programm MAIN:
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
Beispiel mit Funktionsbaustein:
Funktionsbaustein FB_Dynamic:
{attribute 'enable_dynamic_creation'}
FUNCTION_BLOCK FB_Dynamic
VAR
nCounts : INT;
END_VAR
Methode Increase:
METHOD Increase : INT
VAR_INPUT
nCountStep : INT;
END_VAR
nCounts := nCounts + nCountStep;
Increase := nCounts;
Programm MAIN:
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
Beispiel mit Array:
Programm MAIN:
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