PDA

Просмотр полной версии : [Вопрос] Почему не стоит возвращать строки в вызываемых функциях?



Sersoftin
30.10.2014, 02:58
В процессе написания мода я решил пойти на такую крайность: вернуть значение строки в stock. На этом форуме есть тема оптимизации. Там пишут, что этого делать не стоит и это грозит переполнением стека. Я хотел бы увидеть программный код, который способен вызвать это переполнение возвратом стринга в стоке.

В теме приводится пример с получением ника игрока. Я сделал такое:

CMD:go(playerid, params[])
{
for (new i; i<=1000;i++)
print(PlayerName(playerid));
print("completed");
}

stock PlayerName(playerid)
{
new pname[MAX_PLAYER_NAME];
GetPlayerName(playerid,pname,sizeof(pname));
return pname;
}

И ничего особенного не заметил. Все отработало корректно. Так как же вызвать переполнение стека возвратом стринга?

DeimoS
30.10.2014, 10:47
А верните не 24 ячейки, а, например, 2048

main()
{
new dest[2048];
dest = get_crash();
print(dest);
}

stock get_crash()
{
new src[2048] = "Этот код заставит сервер вывести ошибку Runtime Error";
return src;
}
и подключите crashdetect.

И да, ник уже давно все получают в OnPlayerConnect, а далее вызывают массив, в котором этот ник записан

#ball
30.10.2014, 11:09
И да, ник уже давно все получают в OnPlayerConnect, а далее вызывают массив, в котором этот ник записан
Это понятно,пример был взят с темы об оптимизации.


main()
{
new dest[2048];
dest = get_crash();
print(dest);
}

stock get_crash()
{
new src[2048] = "Этот код заставит сервер вывести ошибку Runtime Error";
return src;
}
Ну а зачем возвращать такое огромное число ячеек,врид ли такое где то будет.Если поставить не 2048,а 128,то все отлично работает и без ошибок.

MR_BEN
30.10.2014, 11:29
Это если один такой сток, а если их будет больше?

DeimoS
30.10.2014, 11:44
Ну а зачем возвращать такое огромное число ячеек,врид ли такое где то будет.Если поставить не 2048,а 128,то все отлично работает и без ошибок.

Ну хорошо, сделай так:

main()
{
new dest[4070];
PlayerName();
print(dest);
}
stock PlayerName()
{
new pname[MAX_PLAYER_NAME];
pname = "Azaza";
return PlayerName;
}
И посмотри на количество занятого стэка (если не установлен режим отладки, то перед этим зайди в папку с pawno и создай там файл "pawn.cfg", в котором пропиши "-d3" и после уже компилируй).
А после

return PlayerName;
замени на

return 1;
И опять посмотри.

С возвратом единицы в стэке будет занято 4105 ячейки (4105*4 = 16420 байт), а с возвратом массива уже будет занято 4130 (4130*4 = 16520 байт).
То есть, если ты возвращаешь массив, он в стэке занимает в 2 раза больше места (сначала в стоке создаётся, а после в функции, где вызывается сток, резервируется столько же памяти, дабы вернувшийся результат было где хранить).
Если ты будешь это всё делать в new.pwn, где у тебя будет лишь один массив на 100 ячеек и сток с массивом в 50 ячеек, которые ты будешь возвращать, проблем, естественно, не будет. Но если у тебя будет целый мод, в котором создано уже с десяток массивов в одном лишь OnGameModeInit, а ты там ещё и десяток возвратов сделаешь... Сам понимаешь, стэк очень быстро кончится

- - - Добавлено - - -


Это понятно,пример был взят с темы об оптимизации.

Ну а зачем возвращать такое огромное число ячеек,врид ли такое где то будет.

И да. Не говори гоп, пока не перепрыгнешь. Нужды бывают разные и если ты с таким ещё не столкнулся - не значит, что такого не может быть

#ball
30.10.2014, 12:05
Ну хорошо, сделай так:

main()
{
new dest[4070];
PlayerName();
print(dest);
}
stock PlayerName()
{
new pname[MAX_PLAYER_NAME];
pname = "Azaza";
return PlayerName;
}
И посмотри на количество занятого стэка (если не установлен режим отладки, то перед этим зайди в папку с pawno и создай там файл "pawn.cfg", в котором пропиши "-d3" и после уже компилируй).
А после

return PlayerName;
замени на

return 1;
И опять посмотри.

С возвратом единицы в стэке будет занято 4105 ячейки (4105*4 = 16420 байт), а с возвратом массива уже будет занято 4130 (4130*4 = 16520 байт).
То есть, если ты возвращаешь массив, он в стэке занимает в 2 раза больше места (сначала в стоке создаётся, а после в функции, где вызывается сток, резервируется столько же памяти, дабы вернувшийся результат было где хранить).
Если ты будешь это всё делать в new.pwn, где у тебя будет лишь один массив на 100 ячеек и сток с массивом в 50 ячеек, которые ты будешь возвращать, проблем, естественно, не будет. Но если у тебя будет целый мод, в котором создано уже с десяток массивов в одном лишь OnGameModeInit, а ты там ещё и десяток возвратов сделаешь... Сам понимаешь, стэк очень быстро кончится

- - - Добавлено - - -



И да. Не говори гоп, пока не перепрыгнешь. Нужды бывают разные и если ты с таким ещё не столкнулся - не значит, что такого не может быть

Благодарю за ответ.Все понял)