Skip to main content

Atributo: estimated-stack-usage

El pragma proporciona un valor estimado para el requisito de tamaño de pila.

Los métodos con llamadas recursivas no pueden pasar una verificación de pila porque no se puede determinar el uso de la pila. Como resultado, se emite una advertencia. Para evitar esta advertencia, puede darle al método un valor estimado (en bytes) para el requisito de tamaño de pila. Luego, el método pasa la verificación de pila con éxito.

Sintaxis

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

Insertar ubicación: primera línea sobre la parte de declaración del método.

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


Para más información, ver: llamada de método

Llamada de método recursivo

Dentro de su implementación, un método puede llamarse a sí mismo, ya sea directamente mediante el THIS puntero, o por medio de una variable local para el bloque de función asignado.

Sugerencia

Utilice recursiones principalmente para procesar tipos de datos recursivos, como listas vinculadas. En general, recomendamos tener cuidado al usar la recursividad, ya que las recurrencias inesperadamente profundas pueden provocar un desbordamiento de la pila y tiempo de inactividad de la máquina.

ejemplo 265. Cálculo del factorial

el siguiente programa PLC_PRG calcula el factorial de un número en el FB_Factorial bloque de función de una manera diferente, cada uno en su propio método.

  • Método m_Iterative: Iterativo

  • Método m_Pragmaed: Recursivo con supresión de advertencia

  • Método m_Recursive: recursivo

  • Método m_Temp: Temporal con supresión de advertencia

Se emite una advertencia para el m_Recursive método solamente.

_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 el m_Recursive emite una advertencia cuando se ejecuta el programa.

_cds_img_example_pragma_estimate_stack_usage_in_runtime.png