Skip to main content

Operator: __NEW

Der Operator ist eine Erweiterung der Norm IEC 61131-3.

Der __NEW-Operator reserviert dynamisch Speicher um Funktionsbausteine, benutzerdefinierte Datentypen oder Arrays von Standarddatentypen zu instanzieren. Der Operator gibt einen passend getypten Pointer zurück.

Voraussetzung: Im Eigenschaftendialog der übergeordneten Applikation, in der Registerkarte Optionen Applikationserzeugung, ist die Option Dynamische Speicherallozierung verwenden aktiviert.

Syntax

<pointer name> := __NEW( <type> ( , <size> )? );
__DELETE( <pointer name> );

<type> : <function block> | <data unit type> | <standard data type>

Der Operator 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 Größe <size>. Wenn der Versuch Speicher zu allozieren scheitert, gibt __NEW den Wert 0 zurück.

Verwenden Sie den Operator innerhalb der Zuweisung „:=„, ansonsten wird eine Fehlermeldung ausgegeben.

Ein Funktionsbaustein oder ein benutzerdefinierter Datentyp, 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. Das ist bei Funktionsbausteinen, die Teil einer Bibliothek sind, nicht erforderlich.

Tipp

Wenn Sie im Onlinebetrieb das Datenlayout des Funktionsbausteins ändern, können Sie anschließend kein Einloggen mit Online-Change ausführen. Der Speicherbereich der Funktionsbaustein-Instanz ist nämlich ungültig geworden. Eine Änderung des Datenlayouts nehmen Sie vor, wenn Sie beim Funktionsbaustein neue Variablen hinzufügen, bestehende Variablen löschen oder Datentypen von Variablen ändern.

Beispiel 150. Beispiel

Array (DWORD)

PROGRAM PLC_PRG
VAR
        pdwScalar : POINTER TO DWORD; //Typed pointer
        xInit : BOOL := TRUE;
        xDelete : BOOL;
END_VAR

IF (xInit) THEN
        pdwScalar := __NEW(DWORD, 16); // Allocates memory (16 dwords) and assigns them to pointer pdwScalar
END_IF
IF (xDelete) THEN
        __DELETE(pdwScalar); // Frees memory of pointer
END_IF

Funktionsbaustein

{attribute 'enable_dynamic_creation'}
FUNCTION_BLOCK FBComputeGamma
VAR_INPUT
        iAlpha : INT;
        iBeta : INT;
END_VAR
VAR_OUTPUT
        iGamma : INT;
END_VAR
VAR
END_VAR

iGamma := iAlpha + iBeta;

PROGRAM PLC_PRG
VAR
        pComputeGamma : POINTER TO FBComputeGamma;      // Typed pointer
        xInit : BOOL := TRUE;
        xDelete : BOOL;
        iResult : INT;
END_VAR

IF (xInit) THEN
        pComputeGamma := __NEW(FBComputeGamma); // Allocates memory
        xInit := FALSE;
END_IF
pComputeGamma^.iAlpha := (pComputeGamma^.iAlpha + 1)MOD 100; // Sets first input of pComputeGamma
pComputeGamma^.iBeta := 10; // Sets second input of pComputeGamma
pComputeGamma^(); // Calls the FB pComputeGamma is pointing to
iResult := pComputeGamma^.iGamma; // Reads output of pComputeGamma
IF (xDelete) THEN
    __DELETE(pComputeGamma); // Frees memory
END_IF

Benutzerdefinierter Datentyp (DUT)

{attribute 'enable_dynamic_creation'}
TYPE ABCDATA :
STRUCT
             iA, iB, iC, iD : INT;
END_STRUCT
END_TYPE

PROGRAM PLC_PRG
VAR
        pABCData : POINTER TO ABCDATA; // Typed pointer
        xInit : BOOL := TRUE;
        xDelete : BOOL;
END_VAR

IF (xInit) THEN
    pABCData := __NEW(ABCDATA); // Allocates memory
    xInit := FALSE;
END_IF
IF (xDelete) THEN
    __DELETE(pABCData); // Frees memory
END_IF

Array (BYTE)

PROGRAM PLC_PRG
VAR
        pbDataAlpha : POINTER TO BYTE;
        pbDataBeta : POINTER TO BYTE;
        xInit : BOOL := TRUE;
        xDelete : BOOL;
        usiCnt : USINT;
        bTestC: BYTE;
END_VAR

IF (xInit) THEN
        pbDataAlpha := __NEW(BYTE, 16); // Allocates 16 bytes for pbDataAlpha
        pbDataBeta := __NEW(BYTE);  // Allocates memory for pbDataBeta
        xInit := FALSE;

        FOR usiCnt := 0 TO 15 DO
                pbDataAlpha[usiCnt] := usiCnt; // Writes to new array
        END_FOR
        pbDataBeta^:= 16#FF; // Writes to new data
END_IF

bTestC := pbDataAlpha[12];  // Reads new array by index access

IF (xDelete) THEN // Frees memory
        __DELETE(pbDataAlpha);
        __DELETE(pbDataBeta);
END_IF


Wichtig

Es ist nicht ratsam, zwei Tasks gleichzeitig auszuführen, die beide den __NEW-Operator aufrufen. Entweder Sie verwenden ein Semaphor (SysSemEnter) oder eine vergleichbare Technik, um einen konkurrierenden Aufruf von __NEW zu verhindern. Das bewirkt allerdings, dass bei umfangreicher Nutzung von __NEW ein höherer Jitter entsteht.

Empfehlenswert ist, nur in einer Task __NEW-Operatoren aufzurufen.