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 für diese Methoden ausgegeben. Um die Warnung zu unterdrücken, können Sie der Methode mit Hilfe des Attributs 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:
{attribute 'estimated-stack-usage' := '99'} // 99 bytes
METHOD SampleMethod : INT 
VAR_INPUT
END_VARAusgegebene Warnung:
Die Warnung, die für rekursive Methoden ohne Attribut 'estimated-stack-usage' ausgegeben wird, lautet:
„C0298: Berechnung des Stackverbrauchs aufgrund rekursiver Aufrufe unvollständig, beginnend bei '<FB.Methode>'“
In einem Projekt, das im Vergleich zum letzten Erstellen des Projekts unverändert ist, wird die Warnung nur bei Verwendung des Befehls Projekt neu erstellen ausgegeben (nicht bei Verwendung des Befehls Projekt erstellen).
Einstellung der Stackgröße:
Der Wert der maximal möglichen Stackgröße kann in den Real-Time Einstellungen des TwinCAT-Projekts konfiguriert werden (Registerkarte Settings > Global Task Config/Maximal Stack Size [KB]). Der eingestellte Maximalwert steht dabei nicht komplett dem SPS-Projekt zur Verfügung, sondern wird z. B. ein Teil davon vom TwinCAT-Laufzeitsystem gebraucht.
|  | Keine Stackberechnung für Stand-alone SPS-Projekte Aufgrund der Abkoppelung vom System Manager ist eine Berechnung des Stackverbrauchs für ein Stand-alone SPS-Projekt nicht möglich. | 
Rekursiver Methodenaufruf
Innerhalb der zugehörigen Implementierung kann sich eine Methode selbst aufrufen: entweder direkt mit Hilfe des THIS-Pointers oder mit Hilfe einer lokalen Variablen für den zugeordneten Funktionsbaustein.
| Hinweis | |
| Maschinenstillstand durch möglichen Stacküberlauf Bei unerwartet tiefen Rekursionen kann es zu einem Stacküberlauf und damit zu einem Maschinenstillstand kommen. 
 | 
Beispiel: Berechnung der Fakultät
Innerhalb des Funktionsbausteins FB_Factorial wird die Fakultät einer Zahl auf unterschiedliche Weise berechnet. Die verschiedenen Berechnungen finden jeweils in einer eigenen Methode statt.
- Methode Iterative: Iterativ
- Methode Pragmaed: Rekursiv mit Warnungsunterdrückung
- Methode Recursive: Rekursiv
Bei der Neuerstellung des Projekts erzeugt nur die Methode Recursive die Warnung C0298.
Struktur ST_FactorialResult zur Speicherung der Werte:
// Contains the data of the factorial calculation of nNumber.
TYPE ST_FactorialResult :
STRUCT
    nNumber    : USINT;
    nIterative : UDINT;
    nRecursive : UDINT;
    nPragmaed  : UDINT;
END_STRUCT
END_TYPEFunktionsbaustein FB_Factorial zur Berechnung der Fakultät:
// Factorial calculation in different ways
FUNCTION_BLOCK FB_Factorial
VAR
     nNumberIterative    : UINT;
END_VARProperty nNr samt Set-Funktion, zur Übergabe des Parameters für die iterative Methode:
{attribute 'monitoring' := 'variable'}
PROPERTY nNr : UINTnNumberIterative := nNr;Iterative Berechnungsmethode:
// Iterative calculation
METHOD PUBLIC Iterative : UDINT
VAR
    nCnt : UINT;
END_VARIterative := 1;
 
IF nNumberIterative > 1 AND nNumberIterative <= 12 THEN
    FOR nCnt := 1 TO nNumberIterative DO
        Iterative := Iterative * nCnt;
    END_FOR;
    RETURN;
ELSE
    RETURN;
END_IFRekursive Berechnungsmethode mit Attribut zur Unterdrückung der Warnung C0298:
// Recursive calculation with suppressed warning
{attribute 'estimated-stack-usage' := '200'}
METHOD PUBLIC Pragmaed : UDINT
VAR_INPUT
    nNumber : USINT;
END_VARPragmaed := 1;
 
IF nNumber > 1 AND nNumber <= 12 THEN
    Pragmaed := nNumber * THIS^.Pragmaed(nNumber := (nNumber - 1));
    RETURN;
ELSE
    RETURN;
END_IFDer Pragma-Parameter zur Angabe des geschätzten Stackgrößenbedarfs wird beispielhaft auf 200 Byte gesetzt. Dem liegt die folgende Berechnung zugrunde:
Stackverbrauch pro Methodenaufruf:
Rückgabewert UDINT + Eingangsparameter USINT + Methodenpointer = 4 Byte + 1 Byte + 8 Byte = 13 Byte
Stackverbrauch bei maximal 12 Aufrufen:
12 * 13 Byte = 156 Byte, aufgerundet auf 200 Byte
Rekursive Berechnungsmethode:
// Recursive calculation
METHOD PUBLIC Recursive : UDINT
VAR_INPUT
    nNumber : USINT;
END_VARRecursive := 1;
IF nNumber > 1 AND nNumber <= 12 THEN
    Recursive := nNumber * THIS^.Recursive(nNumber := (nNumber - 1) );
    RETURN;
ELSE
    RETURN;
END_IFHauptprogramm MAIN:
PROGRAM MAIN
VAR
    fbFactorial : FB_Factorial;
    stFactorial : ST_FactorialResult := (nNumber := 9);
END_VAR// Iterativ
fbFactorial.nNr        := stFactorial.nNumber;
stFactorial.nIterative := fbFactorial.Iterative();
// Recursive
stFactorial.nRecursive := fbFactorial.Recursive(nNumber := stFactorial.nNumber);
// Pragmaed
stFactorial.nPragmaed  := fbFactorial.Pragmaed(nNumber := stFactorial.nNumber);