Эмм, нет. Ничего не выделяется на каждый блок. Есть просто стэк, под который изначально выделяется заданное количество памяти, а уже после эта память используется коллбэками.
Не для каждого коллбэка в отдельности свой стэк, а один общий (ибо Pawn однопоточен и всё такое).
Но подсчёт происходит для каждого коллбэка/функции в отдельности, ибо данные в стэке начинают записываться при начале обработки того или иного коллбэка/функции и удаляются из стэка только когда происходит возврат какого-либо значения (return). И то значение, которое компилятор выдаёт после компиляции, в статистике, не является суммой всех локальных переменных/массивов и прочего в моде, а вычисляется исходя из конкретной функции вашего скрипта, которая потребляет больше всего памяти.
Ну, то есть, как я сказал ранее, для каждой функции компилятор рассчитывает стэк в отдельности, ибо когда функция возвращает значение, вся информация удаляется из стэка и, соответственно, места для новой информации вновь становится столько же, сколько было изначально. Из этого получается, что если, например, OnPlayerConnect потребляет 90% стэка (больше всего в скрипте), а OnDialogResponse всего 50%, достаточно указать значение OnPlayerConnect, которое является самым большим и которого, соответственно, хватит для остальных функций.
- - - Добавлено - - -
Вообще каждый сам может наглядно поэкспериментировать со стэком, включив режим отладки (-d3) и создавая разные массивы.
Например, мои слова о том, что локальные переменные/массивы существуют только в том блоке, в котором они объявлены, проверяются следующим образом:
Сначала сделаем 3 массива в одном блоке кода
PHP код:
public OnGameModeInit()
{
new string1[1000];
string1[0] = 0;
string1[1] = string1[0];
new string2[1000];
string2[0] = 0;
string2[1] = string2[0];
new string3[1000];
string3[0] = 0;
string3[1] = string3[0];
return 1;
}
И получим следующую статистику:
А после вынесем каждый массив в свой блок кода
PHP код:
public OnGameModeInit()
{
{
new string1[1000];
string1[0] = 0;
string1[1] = string1[0];
}
{
new string2[1000];
string2[0] = 0;
string2[1] = string2[0];
}
{
new string3[1000];
string3[0] = 0;
string3[1] = string3[0];
}
return 1;
}
И уже результат будет таков:
То бишь
PHP код:
public OnGameModeInit()
{
{// Первый блок кода открылся
new string1[1000];// В стеке зарезервировалось 1000 ячеек под метку "string1"
string1[0] = 0;
string1[1] = string1[0];
}// Блок закончился и зарезервированные ячейки перестали быть зарезервированными
{
new string2[1000];// Этот массив занял не новые 1000 ячеек, а те, что занимал прошлый массив
string2[0] = 0;
string2[1] = string2[0];
}// И опять всё отчистилось
{
new string3[1000];// И опять прошлые 1000 ячеек
string3[0] = 0;
string3[1] = string3[0];
}// В итоге этот код занял не 3к ячеек, а всего 1к
return 1;
}
Но сразу хочу сказать, что не нужно бояться переполнения стэка. Не в том смысле, что оно безвредно, а в том, что размер стэка всегда можно увеличить, если вам действительно нужно это. Создавая глобальные массивы ради экономии стэка или перенося массивы в сегмент данных путём приписывания атрибута static, вы лишь выделяете новую память, ничего не экономя. Я не говорю, что это плохо (всё зависит от конкретной ситуации и конкретных нужд). Просто не нужно бояться. Разберитесь во всём этим и пользуйтесь памятью осознанно, а не опирайтесь на какие-то слухи, не понимая их.
P.S. Я всё же постараюсь в ближайшее время выделить время на написание статьи о памяти, которую планировал уже очень дано, и там уже постараюсь описать всё это подробнее.