Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Страница 3 из 9 ПерваяПервая 1 2 3 4 5 ... ПоследняяПоследняя
Показано с 21 по 30 из 87
  1. #21
    Аватар для PawnoNoob
    Пользователь

    Статус
    Оффлайн
    Регистрация
    31.03.2016
    Сообщений
    257
    Репутация:
    3 ±
    Цитата Сообщение от DeimoS Посмотреть сообщение
    Там было сравнительно небольшое переполнение стэка, которое компенсировалось тем, что коллбэк, отжирающий такое большое кол-во стэка, не выполнялся весь сразу, а в нём выполнялись лишь определённые условия и то самое переполнение стэка просто не успевало происходить. Вот тебе простой пример настоящего переполнения стэка.
    PHP код:
    #pragma dynamic 80
    main()
    {
        new 
    string[100];
        
    format(stringsizeof(string), "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd");
        print(string);
        print(
    "Ура, я сработал!");

    Есть два исхода ситуации для обработки этого кода: с Jit-плагина и без Jit-плагина. Но начать я бы хотел с краткого объяснения того, как работает стэк.

    А понять надо именно то, что в стэк данные записываются не обычным образом: от начала к концу (1, 2, 3, 4, 5...), а каждый новый элемент попадает в начало (...5, 4, 3, 2, 1). Проще всего стэк представить как стопку тарелок. Ты не можешь взять тарелку из середины стопки, и засунуть тарелку в середину тоже не можешь. Ты можешь работать только с вершиной стопки. Так же и в стэке. Ему просто не нужно структурировать себя иначе, ибо вся информация попадает в него непрерывным потоком и выдаётся она так же непрерывным потоком (напомню, что стэк, по сути своей, похож на оперативную память, в которую данные загрузились, обработались и тут же выгрузились).
    Ну а теперь вернёмся к исходам.

    • Исход №1: (сразу предупреждаю, с Jit-компиляцией я знаком поверхностно и всё, что я напишу ниже - лишь мои предположения того, почему ошибок о переполнении стэка не появляется)
      Особенность Jit-плагина в том, что он не работает с скомпилированным кодом напрямую, а, фактически, компилирует его прямо на ходу. Из-за этого получается так, что все инструкции для работы серверной машины формируются прямо на месте обработки кода => и инструкции по заносу данных в стэк так же формируются на ходу => из-за этого данные, в случае переполнения, просто перезапишут друг друга и если это не приведёт к каким-то серьёзным последствиям (не перезапишется какая-то важная информация или же переполнение будет очень уж большим) - код обработается, но результатом работы будет порча данных.

      В нашем случае, если выделить больше ~ 85 ячеек под стэк - оба сообщения отобразятся нормально, а пострадает лишь информация о вызываемых функциях (при обработке в стэк сначала запишется информация о массиве, после запишется информация о вызове format, а после уже информация о print. Но вспомним про стопкообразную структуру стэка и тут следует понять, что информация print просто займёт место о данных о format... Дальше, возможно, будет понятнее :) )
      Если же выделить меньше 85 ячеек, "буфера" из информации о вызываемых функциям (а это имя самой функции + информация о параметрах) уже не хватит и строка из print с сообщением "Ура, я сработал!" начнёт "заезжать" на строку из массива, которую мы отобразили ранее и которая в стеке будет находится сразу за строкой "Ура, я сработал!". Следовательно, нуль-символ строки "Ура, я сработал!" будет перезаписан на один из других символов и строки будут отображены вместе, ибо ближайший нуль-символ будет только в массиве. И чем меньше вы выделите памяти под стэк, тем больше строка "Ура, я сработал!" начнёт "съедать" той информации, что была записана ранее. И в консоль начнут отображаться различные лишние символы. Так будет до тех пор, пока вы не уменьшите стэк до тех пор, когда даже для строки "Ура, я сработал!" не хватит места. Тогда даже с Jit -плагином случится ошибка, которая сообщит о переполнении стэка

    • Исход №2:
      Без Jit-плагина даже переполнение на 1 ячейку вызовет ошибку у сервера при обработке кода и весь последующий код (в нашем случае это строка "Ура, я сработал!"), что находился в коллбэке/функции после злополучной строки с переполнением, обработан не будет. А теперь представь, что у тебя таких переполнений несколько по всему моду и они находятся в разных коллбэках/функциях и вызываются разными условиями. И тут, когда у тебя на сервере большой онлайн и, соответственно, частота вызова разных участков кода возрастает, вероятность вызова "больного" кода так же возрастает и начинаются различные проблемы, когда у тебя то одна система начинает работать не правильно (стэк переполнился и код перестал обрабатываться => каким-то переменным не присвоились нужные значения, какие-то функции не вызвались и т.п.), то другая. И ты не можешь понять что происходит, ведь, вроде бы, код весь нормально построен и все условия срабатывают...


    И это лишь пример с двумя строками. А данные, которые уже не влезут в сам стэк, могут быть совершенно любыми и последствия могут быть совершенно разными.
    Очень хорошо написано, но я не думаю, что новичкам, в том числе и мне, это сразу всё будет понятно. Как я понял, под string для формата нужно выделять столько ячеек, сколько требуется для самого вывода текста в чат, например, верно?
    Для примера (возможно, я не так понял): команда /kick с выводом текста в чат с помощью format:
    PHP код:
    new string[103];
    format(stringsizeof(string), "Администратор %s кикнул игрока %s. Причина: %s"получаем ник администратораполучаем ник кикнутого игрокавыводим причину.);
    SendClientMessageToAll(цветstring); 
    Для получения и вывода никнеймов используется 48 символов (24+24), верно? Для причины кика используется 15 символов. Всего с учётом текста и никнеймов с причиной используется максимум 103 символа. Можно ли выделить, например, 105? Или же ровно 103 и ничуть не больше?

    И вот насчёт чата. Я, конечно, не такой уж профессионал в плане программирования (это дело времени), но сама функция (сток), который я нашёл в интернете (ясно, что я сам не напишу, так как знаний у меня... очень мало), не очень мне нравится в плане самого кода, уж очень заморочено это всё сделано:
    PHP код:
    stock ProxDetector(playeridFloat:rangecolstring[])
    {
        new 
    Float:pos[3], Float:rad;
        
    GetPlayerPos(playeridpos[0], pos[1], pos[2]);
        foreach(
    Playeri)
        {
            if(
    IsPlayerConnected(i) && GetPlayerVirtualWorld(playerid) == GetPlayerVirtualWorld(i))
            {
                
    radius GetPlayerDistanceFromPoint(ipos[0], pos[1], pos[2]);
                if(
    radius range/16SendClientMessage(icolstring);
                else if(
    rad range/8SendClientMessage(icolstring);
                else if(
    rad range/4SendClientMessage(icolstring);
                else if(
    rad range/2SendClientMessage(icolstring);
                else if(
    rad rangeSendClientMessage(icolstring);
            }
        }
        return 
    1;

    И выводится это в чат с помощью OnPlayerText, что логично:
    (из моего мода)
    PHP код:
    new string[128];
    format(stringsizeof(string), "%s[%d]: %s"textполучение никнеймаplayerid);
    ProxDetector(playerid20.0цветstring); 
    Что вот можно сделать, чтобы чат работал нормально и чтобы не было этих выходов за границы монитора?

  2. #22
    Аватар для Profyan
    Пользователь

    Статус
    Оффлайн
    Регистрация
    23.12.2013
    Адрес
    Омск
    Сообщений
    196
    Репутация:
    22 ±
    Зачем тебе выделять больше памяти? Наша задача наоборот минимизировать затраты,чтобы повысить производительность.

    Про ProxDetector:Есть и другие варианты,более простые. Если разобраться,то тут ничего тяжелого нет. И в этой самописной функции использован стандартный вывод сообщения игроку (SendClientMessage).А через него нельзя вывести,как уже выше упомянули,больше 144 символов.



    Любой дурак может написать код, понятный компьютеру. Хороший программист пишет код, понятный человеку
    Мартин Фаулер


    Skype
    profan99
    VK
    click




  3. #23
    Аватар для PawnoNoob
    Пользователь

    Статус
    Оффлайн
    Регистрация
    31.03.2016
    Сообщений
    257
    Репутация:
    3 ±
    Цитата Сообщение от Profyan Посмотреть сообщение
    Зачем тебе выделять больше памяти? Наша задача наоборот минимизировать затраты,чтобы повысить производительность.

    Про ProxDetector:Есть и другие варианты,более простые. Если разобраться,то тут ничего тяжелого нет. И в этой самописной функции использован стандартный вывод сообщения игроку (SendClientMessage).А через него нельзя вывести,как уже выше упомянули,больше 144 символов.
    Про выделение я просто спросил, так как терзали (да и до сих пор терзают) сомнения насчёт этого. И где найти эти "лёгкие" варианты?

  4. #24
    Аватар для Profyan
    Пользователь

    Статус
    Оффлайн
    Регистрация
    23.12.2013
    Адрес
    Омск
    Сообщений
    196
    Репутация:
    22 ±



    Любой дурак может написать код, понятный компьютеру. Хороший программист пишет код, понятный человеку
    Мартин Фаулер


    Skype
    profan99
    VK
    click




  5. Пользователь сказал cпасибо:
    PawnoNoob (04.04.2016)
  6. #25
    Аватар для ziggi
    Проверенный

    Статус
    Оффлайн
    Регистрация
    14.05.2015
    Сообщений
    1,181
    Репутация:
    790 ±
    Оригинальная функция ProxDetector выводит сообщения игрокам поблизости, причём цвет сообщений меняется в зависимости от расстояния между игроками. Вы почему-то убрали эту особенность из своих функций, вот правильная:
    PHP код:
    stock ProxDetector(playeridFloat:max_rangecolorstring[])
    {
        new
            
    Float:pos_x,
            
    Float:pos_y,
            
    Float:pos_z,
            
    world,
            
    Float:range,
            
    alpha;
        
        
    GetPlayerPos(playeridpos_xpos_ypos_z);
        
    world GetPlayerVirtualWorld(playerid);

        foreach (new 
    Player) {
            if (!
    IsPlayerStreamedIn(playeridi) || world != GetPlayerVirtualWorld(i)) {
                continue;
            }

            
    range GetPlayerDistanceFromPoint(ipos_xpos_ypos_z);
            
    alpha floatround((max_range range) / max_range 255.0);
            
            
    SendClientMessage(icolor & (0xFFFFFF00 alpha), string);
        }

        return 
    1;

    Последний раз редактировалось ziggi; 06.04.2016 в 22:49.

  7. 3 пользователя(ей) сказали cпасибо:
    Nash_Brigers (04.04.2016) Nexius_Tailer (04.04.2016) PawnoNoob (04.04.2016)
  8. #26
    Аватар для PawnoNoob
    Пользователь

    Статус
    Оффлайн
    Регистрация
    31.03.2016
    Сообщений
    257
    Репутация:
    3 ±
    Цитата Сообщение от ziggi Посмотреть сообщение
    Оригинальная функция ProxDetector выводит сообщения игрокам поблизости, причём цвет сообщений меняется в зависимости от расстояния между игроками. Вы почему-то убрали эту особенность из своих функций, вот правильная:
    PHP код:
    stock ProxDetector(playeridFloat:max_rangecolorstring[])
    {
        new
            
    Float:pos_x,
            
    Float:pos_y,
            
    Float:pos_z,
            
    world,
            
    Float:range,
            
    alpha;
        
        
    GetPlayerPos(playeridpos_xpos_ypos_z);
        
    world GetPlayerVirtualWorld(playerid);

        foreach (new 
    Player) {
            if (!
    IsPlayerStreamedIn(playeridi) || world != GetPlayerVirtualWorld(i)) {
                continue;
            }

            
    range GetPlayerDistanceFromPoint(ipos_xpos_ypos_z);
            
    alpha floatround((max_range range) / max_range 255.0));
            
            
    SendClientMessage(icolor & (0xFFFFFF00 alpha), string);
        }

        return 
    1;

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

    Надеюсь, что и этот вопрос, который я задавал раньше, не будет проигнорирован, потому что особо на его никто не ответил:
    цитирую себя же:
    Очень хорошо написано, но я не думаю, что новичкам, в том числе и мне, это сразу всё будет понятно. Как я понял, под string для формата нужно выделять столько ячеек, сколько требуется для самого вывода текста в чат, например, верно?
    Для примера (возможно, я не так понял): команда /kick с выводом текста в чат с помощью format:
    PHP код:
    new string[103];
    format(stringsizeof(string), "Администратор %s кикнул игрока %s. Причина: %s"получаем ник администратораполучаем ник кикнутого игрокавыводим причину.);
    SendClientMessageToAll(цветstring); 
    Для получения и вывода никнеймов используется 48 символов (24+24), верно? Для причины кика используется 15 символов. Всего с учётом текста и никнеймов с причиной используется максимум 103 символа. Можно ли выделить, например, 105? Или же ровно 103 и ничуть не больше?
    И ещё один вопрос появился: для инклуда foreach обязательно нужна YSI библиотека?
    Последний раз редактировалось PawnoNoob; 04.04.2016 в 22:30.

  9. #27
    Аватар для L0ndl3m
    Пользователь

    Статус
    Оффлайн
    Регистрация
    19.10.2013
    Адрес
    Ярославль
    Сообщений
    1,366
    Репутация:
    774 ±
    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    И ещё один вопрос появился: для инклуда foreach обязательно нужна YSI библиотека?
    Нет.

  10. Пользователь сказал cпасибо:
    PawnoNoob (05.04.2016)
  11. #28
    Аватар для PawnoNoob
    Пользователь

    Статус
    Оффлайн
    Регистрация
    31.03.2016
    Сообщений
    257
    Репутация:
    3 ±
    Спасибо всем за ответы, но на два последних вопроса (если первый так можно назвать) я ещё не получил ответ и очень надеюсь на то, что Вы мне поможете с ответом. Заранее благодарен
    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    В принципе, мне не нужна такая функция, как изменение цвета в зависимости от расстояния. Нужен сток самого ProxDetector без этой функции, просто чтобы люди видели на расстоянии сообщение(-я), а на цвет как-то плевать, если честно, потому что это не особо нужно.
    Я думаю, что те функции, которые мне (и вообще в моде) особо не нужны, можно не использовать.

    Надеюсь, что и этот вопрос, который я задавал раньше, не будет проигнорирован, потому что особо на его никто не ответил:
    цитирую себя же:

    Очень хорошо написано, но я не думаю, что новичкам, в том числе и мне, это сразу всё будет понятно. Как я понял, под string для формата нужно выделять столько ячеек, сколько требуется для самого вывода текста в чат, например, верно?
    Для примера (возможно, я не так понял): команда /kick с выводом текста в чат с помощью format:
    PHP код:
    new string[103];
    format(stringsizeof(string), "Администратор %s кикнул игрока %s. Причина: %s"получаем ник администратораполучаем ник кикнутого игрокавыводим причину.);
    SendClientMessageToAll(цветstring); 
    Для получения и вывода никнеймов используется 48 символов (24+24), верно? Для причины кика используется 15 символов. Всего с учётом текста и никнеймов с причиной используется максимум 103 символа. Можно ли выделить, например, 105? Или же ровно 103 и ничуть не больше?

  12. #29
    Аватар для PawnoNoob
    Пользователь

    Статус
    Оффлайн
    Регистрация
    31.03.2016
    Сообщений
    257
    Репутация:
    3 ±
    Появился ещё один вопрос по format: я создал переменную new string[200]. В диалоговом окне регистрации у меня, например, 200 букв, пробелов, запятых, цифр, точек и т.д., но при этом есть табуляция (/t, /n) и коды цветов ({FFFFFF} и т.д.), с которыми получается примерно 250 символов. Учитываются ли они (цвета, знаки препинания, цифры, табуляция и т.д.) или же format опускает их при подсчёте символов в строке?

  13. #30
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    Очень хорошо написано, но я не думаю, что новичкам, в том числе и мне, это сразу всё будет понятно.
    Ну так работа с памятью - вообще один из самых сложных аспектов программирования. И в Pawn это ещё очень сильно урезано (язык как раз и создавался для того, чтоб облегчить жизнь новичкам при работе с памятью). Я сам ещё не все аспекты знаю (правильнее сказать, многого не знаю)

    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    Как я понял, под string для формата нужно выделять столько ячеек, сколько требуется для самого вывода текста в чат, например, верно?
    Верно. Про нуль-символ, обозначающий конец строки, не забывай
    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    Для получения и вывода никнеймов используется 48 символов (24+24), верно
    Совершенно неверно, ибо в таких случаях нужно использовать макросы, которые предоставляют сами разработчики (в случае с никами - MAX_PLAYER_NAME). Представь, что в следующей версии клиента длину ника увеличат. И все твои массивы придётся вручную пересчитывать. Хотя можно было составить вот такую формулу, которая будет просчитана ещё на этапе компиляции и моду серверу не даст:
    PHP код:
    new string[40+MAX_PLAYER_NAME*2+15+1];
    //40 - кол-во символов в строке "Администратор %s кикнул игрока %s. Причина: %s" без спецификаторов (%s, %d, %f и т.п.), которые считать не нужно, ибо в финальной версии сообщения они заменятся на те данные, что ты выводишь.
    //MAX_PLAYER_NAME*2 - выделяем место под два ника
    //15 - место под причину
    //1 - место под нуль символ 
    и можешь забыть и этом массиве навсегда.

    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    Можно ли выделить, например, 105? Или же ровно 103 и ничуть не больше?
    А зачем выделять больше, чем нужно? Ну можешь платить за хлеб не 15 рублей, а 1500. Хуже от этого продавцу не станет, а вот у тебя будут тратится ресурсы впустую. Так же и в нашем случае

    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    И вот насчёт чата. Я, конечно, не такой уж профессионал в плане программирования (это дело времени), но сама функция (сток), который я нашёл в интернете (ясно, что я сам не напишу, так как знаний у меня... очень мало), не очень мне нравится в плане самого кода, уж очень заморочено это всё сделано:
    PHP код:
    stock ProxDetector(playeridFloat:rangecolstring[])
    {
        new 
    Float:pos[3], Float:rad;
        
    GetPlayerPos(playeridpos[0], pos[1], pos[2]);
        foreach(
    Playeri)
        {
            if(
    IsPlayerConnected(i) && GetPlayerVirtualWorld(playerid) == GetPlayerVirtualWorld(i))
            {
                
    radius GetPlayerDistanceFromPoint(ipos[0], pos[1], pos[2]);
                if(
    radius range/16SendClientMessage(icolstring);
                else if(
    rad range/8SendClientMessage(icolstring);
                else if(
    rad range/4SendClientMessage(icolstring);
                else if(
    rad range/2SendClientMessage(icolstring);
                else if(
    rad rangeSendClientMessage(icolstring);
            }
        }
        return 
    1;

    Какая-то странная функция... Зачем оставлена проверка на увеличение расстояния, если цвет везде один? Да и проверка на подключение игрока в foreach... В общем, вот
    PHP код:
    stock ProxDetector(playeridFloat:rangecolorstring[])
    {
        new 
    Float:pos_x
            
    Float:pos_y
            
    Float:pos_z,
            
    virtualworld GetPlayerVirtualWorld(playerid);
        
    GetPlayerPos(playeridpos_xpos_ypos_z);
        foreach(
    Playeri)
        {
            if(
    virtualworld != GetPlayerVirtualWorld(i)) continue;
            else if(!
    IsPlayerInRangeOfPoint(irangepos_xpos_ypos_z)) continue;
            else 
    SendClientMessage(icolorstring);
        }
        return 
    1;

    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    Что вот можно сделать, чтобы чат работал нормально и чтобы не было этих выходов за границы монитора?
    Это конкретно проблемы твёрдого знака и, возможно, ещё некоторых символов. Я бы просто забил, ибо вряд ли здравомыслящий человек будет забивать весь чат одними твёрдыми знаками в верхнем регистре. Точнее, за это должны наказывать, ибо это флуд. Но если уж очень хочется нагрузить свой сервер лишней работой, путей решения уйма: начиная от запрета ввода большого числа символов в верхнем регистре подряд (проверка циклом) и заканчивая просто обрезанием строки (но тогда нужно либо проверять строку на наличие большого числа злополучных символов, либо пострадают и другие сообщения с нормальными символами и нормально отображающиеся)

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

    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    Появился ещё один вопрос по format: я создал переменную new string[200]. В диалоговом окне регистрации у меня, например, 200 букв, пробелов, запятых, цифр, точек и т.д., но при этом есть табуляция (/t, /n) и коды цветов ({FFFFFF} и т.д.), с которыми получается примерно 250 символов. Учитываются ли они (цвета, знаки препинания, цифры, табуляция и т.д.) или же format опускает их при подсчёте символов в строке?
    Спецсимволы, типа "\t" и "\n" занимают 1 ячейку. Проверить можно так:
    PHP код:
    new string[10] = "\t\n";
    printf("%d"strlen(string)); 
    Код цвета занимает 8 символов
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  14. Пользователь сказал cпасибо:
    PawnoNoob (06.04.2016)
 

 
Страница 3 из 9 ПерваяПервая 1 2 3 4 5 ... ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •