Skip to main content

属性:estimated-stack-usage

pragma 提供了堆栈大小要求的估计值。

具有递归调用的方法无法通过堆栈检查,因为无法确定堆栈使用情况。结果,发出警告。为防止出现此警告,您可以为该方法提供堆栈大小要求的估计值(以字节为单位)。然后该方法成功通过堆栈检查。

句法

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

插入位置:方法声明部分上方的第一行。

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


有关更多信息,请参阅: 方法调用

递归方法调用

在其实现中,方法可以调用自身,或者直接通过 THIS 指针,或通过分配功能块的局部变量。

提示

使用递归主要用于处理递归数据类型,例如链表。一般来说,我们建议在使用递归时要小心,因为意外的深度递归会导致堆栈溢出和机器停机。

265. 阶乘的计算

以下程序 PLC_PRG 计算一个数的阶乘 FB_Factorial 功能块以不同的方式,每个都有自己的方法。

  • 方法 m_Iterative: 迭代

  • 方法 m_Pragmaed: 带有警告抑制的递归

  • 方法 m_Recursive: 递归

  • 方法 m_Temp: 暂时带有警告抑制

发出警告 m_Recursive 方法而已。

_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

只有 m_Recursive 程序执行时发出警告。

_cds_img_example_pragma_estimate_stack_usage_in_runtime.png