Skip to main content

Attributo: estimated-stack-usage

Il pragma fornisce un valore stimato per il requisito della dimensione dello stack.

I metodi con chiamate ricorsive non possono superare un controllo dello stack perché non è possibile determinare l'utilizzo dello stack. Di conseguenza, viene emesso un avviso. Per evitare questo avviso, puoi assegnare al metodo un valore stimato (in byte) per il requisito della dimensione dello stack. Quindi il metodo supera correttamente il controllo dello stack.

Sintassi

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

Inserisci posizione: prima riga sopra la parte di dichiarazione del metodo.

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


Per ulteriori informazioni, vedere: chiamata al metodo

Chiamata ricorsiva al metodo

All'interno della sua implementazione, un metodo può chiamare se stesso, sia direttamente tramite il THIS puntatore o tramite una variabile locale per il blocco funzione assegnato.

Suggerimento

Utilizzare le ricorsioni principalmente per l'elaborazione di tipi di dati ricorsivi come gli elenchi collegati. In generale, si consiglia di prestare attenzione quando si utilizza la ricorsione, poiché le ricorsioni inaspettatamente profonde possono causare overflow dello stack e tempi di fermo macchina.

Esempio 265. Calcolo del fattoriale

Il seguente programma PLC_PRG calcola il fattoriale di un numero in FB_Factorial blocco funzione in modo diverso, ciascuno nel proprio metodo.

  • Metodo m_Iterative: Iterativo

  • Metodo m_Pragmaed: ricorsivo con soppressione degli avvisi

  • Metodo m_Recursive: Ricorsivo

  • Metodo m_Temp: Temporaneo con soppressione degli avvisi

Viene emesso un avviso per il m_Recursive solo metodo.

_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

Solo il m_Recursive emette un avviso quando il programma viene eseguito.

_cds_img_example_pragma_estimate_stack_usage_in_runtime.png