10

我刚才做了一个测试:

function overflow(stack:int = 0):void
{
    if(stack < 5290)
    {
        trace(stack);
        overflow(stack + 1);
    }
}

overflow();

5287这总是在调用后引发 StackOverflow 错误。

错误 #1023:发生堆栈溢出。

这个限制变量是(取决于机器规格、环境等)还是在某处定义的平面值?如果我将if语句更改为小于 5287,我不会收到错误消息。

4

3 回答 3

2

嗯,这很有趣。我查看了 Barış 提供的链接。毕竟,它似乎可能与“方法复杂性”有关,但我不确定如何进一步测试它。我正在使用 Flash CS5,为 Flash Player 10、Actionscript 3 发布(当然)。

原来的:

function overflow(stack:int = 0):void {
    if(stack < 5290){
        trace(stack);
        overflow(stack + 1);
    }
}
// gives 5287

现在向 overflow() 方法添加一个 Math.random() 调用:

function overflow(stack:int = 0):void {
    Math.random();
    if(stack < 5290){
        trace(stack);
        overflow(stack + 1);
    }
}
// gives 4837

添加多个 Math.random() 调用没有区别,也不会将其存储在局部变量中或向 overflow() 方法添加另一个参数以“携带”随机生成的值

function overflow(stack:int = 0):void {
    Math.random();
    Math.random();
    if(stack < 5290){
        trace(stack);
        overflow(stack + 1);
    }
}
// still gives 4837

此时我尝试了不同的数学调用,例如:

// just the change to that 1 line:
Math.pow() // gives 4457
Math.random(), Math.sqrt(), Math.tan(), Math.log() // gives 4837

有趣的是,传递给 Math 类的内容似乎并不重要,但它保持不变:

Math.sqrt(5) vs Math.sqrt(Math.random()) // gives 4837
Math.tan(5) vs Math.tan(Math.random()) // gives 4837
Math.pow(5, 7) vs Math.pow(Math.random(), Math.random()) // 4457

直到我链接了其中的 3 个:

Math.tan(Math.log(Math.random())); // gives 4457

看起来来自该“组”的两个 Math 调用与一个 Math.pow() 调用“相等”?=b 混合 Math.pow() 和其他东西似乎并没有降低价值:

Math.pow(Math.random(), Math.random()); // gives 4457

但是,链接两个 Math.pow():

Math.pow(Math.pow(Math.random(), Math.random()), Math.random()); // 4133

我可以继续说下去,但我想知道是否有某种模式:

Results:   5287, 4837, 4457, 4133
Differences:  450   380   324
于 2013-03-04T06:30:50.097 回答
2

显然它是可变的。由于您真正执行的所有计算都位于堆栈中(反汇编报告代码显示pushbyte指令和其他与堆栈一起使用的东西,作为非操作数算术),因此该值仅报告可以将多少函数上下文放入堆栈直到它溢出。

我决定根据baris 评论中引用的这篇文章对递归阈值进行一些测试。结果相当尴尬。测试环境:FlashDevelop 3.3.4 RTM,Flash播放器调试器10.1.53.64,flash编译模式:release。“调试”模式基本上没有改变数字,也检查过。

Locals number     Iterations (static int)       Iterations (Math.random())   
0                 5306                          
1                 4864                          4856
2                 4850                          4471
3                 4474                          4149
4                 4153                          3870
5                 3871                          3868
6                 3869                          3621
7                 3620                          3404
8                 3403                          3217
9                 3210                          3214
10                3214                          3042
11                3042                          3045
10 mixed          3042     1 value was assigned Math.random() and 9 - static int
10 advancedRandom 2890     1 value was assigned a custom random with 1 parameter

请注意,在后续执行之间,所有这些值都在 10 的范围内变化。“static int”和“Math.random()”是在递归调用函数中分配给本地人的名称。然而,这导致我假设以下内容:

  1. 在递归函数中包含函数调用会增加函数上下文
  2. locals 的内存与其类型一起分配,超过 8 个字节的块,因为添加一个 local 并不总是减少递归限制
  3. 对某个函数添加多个调用不会为函数上下文添加更多内存
  4. “内存块”很可能是 16 字节长,因为这个值是 2^N,添加一个 int 或 Number local 并不总是会减少递归,而且这大于 8,因为 Number 变量的原始值需要8 个字节,是一个双精度浮点数。
  5. 假设#4 是正确的,函数上下文大小的最佳值似乎是 172 字节,总堆栈大小为 912632 字节。这在很大程度上证实了我最初的假设,即 Flash 10 中的堆栈大小实际上是 1 兆字节。当我尝试在其调试器中打开测试 SWF 时,Flash 11 向我显示了更高的数字,但我没有用它进行广泛的测试。
于 2013-03-04T07:55:35.017 回答
0

一定是可变的!刚刚编译了您的示例,我在堆栈溢出之前达到了 5274。

@baris 这就是 mxmlc 编译器

+1 堆栈溢出问题^^

于 2013-03-04T01:00:45.783 回答