__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.

__NEW 1:

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.

__NEW 2:

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;
    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;
    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