__NEW
Der Operator ist eine Erweiterung der Norm IEC 61131-3.
Der __NEW-Operator reserviert dynamisch Speicher um 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.
Keine Typänderung per Online-Change möglich Ein Funktionsbaustein oder ein benutzerdefinierter Datentyp, dessen Instanz mit __NEW dynamisch erzeugt wird, belegt einen fixen Speicherbereich. Er kann sein Datenlayout durch Online-Change nicht ändern. Somit können keine neuen Variablen hinzugefügt und keine gelöscht werden, und es können keine Typen geändert werden. Dadurch ist sichergestellt, dass der Pointer auf dieses Objekt auch nach dem Online-Change gültig ist. Aus diesem Grund kann der Operator __NEW nur auf Funktionsbausteine/DUTs aus Bibliotheken und auf Funktionsbausteine/DUTs mit dem Attribut 'enable_dynamic_creation' angewendet werden. Wenn die Schnittstelle eines solchen Funktionsbausteins/DUTs geändert wird, gibt TwinCAT eine Fehlermeldung aus. |
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. |
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