Skip to main content

Attribut: estimated-stack-usage

Das Pragma übergibt einen Schätzwert für den Stackgrößenbedarf.

Methoden mit rekursivem Aufruf halten einer Stackprüfung nicht stand, weil der Stackverbrauch nicht ermittelt werden kann. Folglich wird eine Warnung ausgegeben. Um diese Warnung zu unterdrücken, können Sie der Methode einen Schätzwert in Bytes für den Stackgrößenbedarf mitgeben. Dann durchläuft die Methode die Stackprüfung erfolgreich.

Syntax

{attribute 'estimated-stack-usage' := ' <estimated stack size in bytes> '}

Einfügeort: Erste Zeile über dem Deklarationsteil der Methode

Beispiel 264. Beispiel
{attribute 'estimated-stack-usage' := '127'} // 127 bytes
METHOD PUBLIC DoIt : BOOL
VAR_INPUT
END_VAR


Für weitere Informationen siehe: Methodenaufruf

Rekursiver Methodenaufruf

Innerhalb ihrer Implementierung kann eine Methode sich selbst aufrufen: entweder direkt mit Hilfe des THIS-Pointers, oder mit Hilfe einer lokalen Variablen für den zugeordneten Funktionsbaustein.

Tipp

Verwenden Sie Rekursionen vorwiegend zur Bearbeitung von rekursiven Datentypen wie beispielsweise verketteten Listen. Allgemein ist es ratsam bei der Verwendung von Rekursion vorsichtig zu sein, da es bei unerwartet tiefen Rekursionen zu eine Stacküberlauf und damit zu einem Maschinenstillstand kommen kann.“

Beispiel 265. Berechnung der Fakultät

Das folgende ProgrammPLC_PRG berechnet die Fakultät einer Zahl im Funktionsbaustein FB_Factorial auf unterschiedliche Weise in jeweils einer eigenen Methode.

  • Methode m_Iterative: Iterativ

  • Methode m_Pragmaed: Rekursiv mit Warnungsunterdrückung

  • Methode m_Recursive: Rekursiv

  • Methode m_Temp: Temporär mit Warnungsunterdrückung

Nur die Methode m_Recursive erzeugt eine Warnung.

_cds_img_example_pragma_estimate_stack_usage.png
// Contains the data  of the factorial calculation of uiNumber
TYPE FACTORIAL_RESULT :
STRUCT
    uiNumber : UINT;
    udiIterative : UDINT;
    udiRecursive : UDINT;
    udiPragmaed : UDINT;
    udiTemp : UDINT;
END_STRUCT
END_TYPE

PROGRAM PLC_PRG
VAR
    fb_Factorial_A : FB_Factorial;
    factorial_A : FACTORIAL_RESULT := (uiNumber := 9, udiIterative := 0, udiRecursive := 0, udiPragmaed := 0 );
END_VAR
fb_Factorial_A.p_Number := factorial_A.uiNumber;
factorial_A.udiIterative := fb_Factorial_A.m_Iterative();
factorial_A.udiRecursive := fb_Factorial_A.m_Recursive(uiN := factorial_A.uiNumber);
factorial_A.udiPragmaed := fb_Factorial_A.m_Pragmaed(uiN := factorial_A.uiNumber);
factorial_A.udiTemp := fb_Factorial_A.m_Temp(uiN := factorial_A.uiNumber);

//Factorial calculation in different ways
FUNCTION_BLOCK FB_Factorial
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
    uiN : UINT;
    udiIterative : UDINT;
    udiPragmaed : UDINT;
    udiRecursive : UDINT;
END_VAR

    // Iterative calculation
    METHOD PUBLIC m_Iterative : UDINT
    VAR
        uiCnt : UINT;
    END_VAR
    m_Iterative := 1;
    IF      uiN > 1 THEN
            FOR uiCnt := 1 TO uiN DO
                    m_Iterative := m_Iterative * uiCnt;
            END_FOR;
            RETURN;
    ELSE
            RETURN;
    END_IF;

    //Recursive calculation with suppressed warning
    {attribute 'estimated-stack-usage' := '99'}
    METHOD PUBLIC m_Pragmaed : UDINT
    VAR_INPUT
            uiN : UINT;
    END_VAR
    VAR
    END_VAR
    m_Pragmaed := 1;
    IF      uiN > 1 THEN
            m_Pragmaed := uiN * THIS^.m_Pragmaed(uiN := (uiN - 1));
            RETURN;
    ELSE
            RETURN;
    END_IF;
    
    //Recursive calculation
    METHOD PUBLIC m_Recursive : UDINT
    VAR_INPUT
            uiN : UINT;
    END_VAR
    VAR
    END_VAR
    m_Recursive := 1;
    IF      uiN > 1 THEN
            m_Recursive := uiN * THIS^.m_Recursive(uiN := (uiN - 1) );
            RETURN;
    ELSE
            RETURN;
    END_IF;
    
    // Called by temporary FB instance
    {attribute 'estimated-stack-usage' := '99'}
    METHOD PUBLIC m_Temp : UDINT
    VAR_INPUT
            uiN : UINT;
    END_VAR
    VAR
            fb_Temp : FB_Factorial;
    END_VAR
    m_Temp := 1;
    IF      uiN > 1 THEN
            m_Temp := uiN * fb_Temp.m_Temp(uiN := (uiN - 1));
            RETURN;
    ELSE
            RETURN;
    END_IF;

PROPERTY p_Number : UINT
uiN := p_Number; //Setter method

Bei der Ausführung des Programms generiert nur die Methode m_Recursive eine Warnung.

_cds_img_example_pragma_estimate_stack_usage_in_runtime.png