Является ли ограничение стека 5287 в AS3 переменной или предопределено?

Я проверил тест только сейчас:

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

overflow();

Это всегда вызывает ошибку StackOverflow после вызовов 5287.

Ошибка # 1023: произошло переполнение стека.

Является ли эта предельная переменная (в зависимости от спецификаций машины, среды и т.д.) или является ли это плоское значение, определенное где-то? Если я изменил оператор if на менее чем 5287, я не получу ошибку.

Ответ 1

Очевидно, это переменная. Поскольку все расчеты, которые вы действительно делаете, расположены в стеке (коды отчетов о разборке показывают инструкции pushbyte и другие материалы, которые работают со стеклом, как арифметика без операнда), это значение только сообщает, сколько контекстов функций может быть помещено в стек до он переполняется.

Я решил запустить некоторые тесты для порогов рекурсии, основанные на этой статье, на которые ссылался бариз. Результаты были довольно смущающими. Тестовая среда: FlashDevelop 3.3.4 RTM, отладчик Flash-плеера 10.1.53.64, режим компиляции вспышки: выпуск. Режим "Отладка" не изменил числа кардинально, тоже проверил.

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

Примечание. Все эти значения варьируются в пределах десяти раз между последующими исполнениями. "Static int" и "Math.random()" являются обозначениями того, что назначено локалям с рекурсивно называемой функцией. Это, однако, заставляет меня предположить следующее:

  • Включение вызовов функций в рекурсивную функцию добавляет в контекст функции
  • Память для локальных жителей назначается вместе с ее типом, в кусках более 8 байтов, поскольку добавление локального не всегда уменьшает предел рекурсии
  • Добавление нескольких вызовов к определенной функции не добавляет больше памяти в контекст функции
  • "Хранение памяти", скорее всего, 16 байтов, потому что это значение равно 2 ^ N, добавление одного int или Number local не всегда уменьшает рекурсию, и это больше, чем 8, в качестве необработанного значения Числовая переменная принимает 8 байтов, являясь плавающей точкой с двойной точностью.
  • Предполагая # 4 правильно, лучшее значение для размера контекста функции оказалось равным 172 байтам, общий размер стека составил 912632 байта. Это в значительной степени подтверждает мое первоначальное предположение о том, что размер стека на самом деле составляет 1 мегабайт во Flash 10. Flash 11 показал мне немного больше чисел, когда я попытался открыть тестовый SWF в своем отладчике, но я не проводил с ним больших испытаний.

Ответ 2

Hm, это интересно. Я взглянул на ссылку, которую дал Барыш. Похоже, что в конце концов это может быть "сложность метода", но я не уверен, как его еще раз проверить. Я использую Flash CS5, публикацию для Flash Player 10, ActionScript 3 (конечно).

Оригинал:

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

Теперь добавление одного метода Math.random() к методу overflow():

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

Добавление нескольких вызовов Math.random() не имеет значения и не сохраняет его в локальной переменной или добавляет другой параметр к методу переполнения() для "переноса" этого случайного сгенерированного значения

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

Ответ 3

Musst быть переменным! Просто скомпилировал ваш образец, и я добрался до 5274 до.

@baris thats для компилятора mxmlc

+1 для вопроса о переполнении стека ^^