Как я могу остановить мой скрипт на C переполнение стека через 1 час? - PullRequest
0 голосов
/ 04 марта 2020

Привет, я новичок в создании сценариев! Я сделал один сценарий для игры, и он перестал работать примерно через 1 час. Код ошибки: «C переполнение стека». Я использую Visual Studio… Я пытаюсь найти любую ошибку в своем коде, но все выглядит нормально! но через 1 час я все еще получаю свою ошибку! Я смотрю на форуме, но я действительно новичок ie в этом. Поэтому я публикую свой код и надеюсь найти кого-то, кто мог бы помочь мне решить мою проблему. Я не могу найти решение, мне нужен кто-то, кто объяснит мне мою ошибку! Спасибо за помощь!

-- Auteur : Max412

GATHER = {}
OPEN_BAGS = true
AUTO_DELETE = {}

MAX_MONSTERS = 8
MIN_MONSTERS = 1

FORBIDDEN_MONSTERS = {}
FORCE_MONSTERS = {}

function hiboux()
    npc:npc(522,3)
    npc:reply(-1)
    exchange:putAllItems()
    global:leaveDialog()
end

function GatherFight()
    for index, actualMap in pairs(mapsWithChangeMap) do
        if (map:onMap(actualMap.map)) then
            if actualMap.gather and actualMap.fight then
                return "both"
            elseif actualMap.gather then
                return "gather"
            elseif actualMap.forcegather then
                return "forcegather"
            elseif actualMap.fight then
                return "fight"
            elseif actualMap.forcefight then
                return "forcefight"
            end
            return "path"
        end
    end
    return false
end

------------------

function move()
    if banque then
        for index, actualMap in pairs(mapsWithChangeMap) do
            if (type(actualMap.path) == "table") then
                if (type(actualMap.toggle) == "table") then
                    for i = 1, #(actualMap.toggle) do
                        actualMap.toggle[i] = false
                    end
                end
            end
        end
        banque = false
    end
    if GatherFight() == "both" then
        return {
            {map = map:currentMap(), custom = processMap, gather = true, fight = true}
        }
    elseif GatherFight() == "gather" then
        return {
            {map = map:currentMap(), custom = processMap, gather = true}
        }
    elseif GatherFight() == "forcegather" then
        return {
            {map = map:currentMap(), custom = processMap, forcegather = true}
        }
    elseif GatherFight() == "fight" then
        return {
            {map = map:currentMap(), custom = processMap, fight = true}
        }
    elseif GatherFight() == "forcefight" then
        return {
            {map = map:currentMap(), custom = processMap, forcefight = true}
        }
    elseif GatherFight() == "path" then
        return {
            {map = map:currentMap(), custom = processMap}
        }
    else
        global:printError("Aucune action sur la map : " .. map:currentMap() .. " | mapID : " .. map:currentMapId())
        global:disconnect()
    end
end

mapsWithChangeMap = {
    {map = "9,8", path = {"bottom", "left"}, gather = true},
    {map = "9,9", path = {"top"}, gather = true},
    {map = "8,8", path = {"left"}, gather = true},
    {map = "7,8", path = {"left"}, gather = true},
    {map = "6,8", path = {"left", "top"}, gather = true},
    {map = "5,8", path = {"left"}, gather = true},
    {map = "4,8", path = {"left"}, gather = true},
    {map = "3,8", path = {"left"}, gather = true},
    {map = "2,8", path = {"left"}, gather = true},
    {map = "1,8", path = {"left"}, gather = true},
    {map = "0,8", path = {"bottom"}, gather = true},
    {map = "0,9", path = {"right"}, gather = true},
    {map = "1,9", path = {"right"}, gather = true},
    {map = "2,9", path = {"right"}, gather = true},
    {map = "3,9", path = {"right"}, gather = true},
    {map = "4,9", path = {"right"}, gather = true},
    {map = "5,9", path = {"right"}, gather = true},
    {map = "6,9", path = {"top"}, gather = true},
    {map = "6,7", path = {"left"}, gather = true},
    {map = "5,7", path = {"top", "left"}, gather = true},
    {map = "4,7", path = {"right"}, gather = true},
    {map = "6,6", path = {"right"}, gather = true},
    {map = "5,6", path = "top", gather = true},
    {map = "5,5", path = "top", gather = true},
    {map = "5,4", path = "top", gather = true},
    {map = "5,3", path = "top", gather = true},
    {map = "5,2", path = "right", gather = true},
    {map = "6,2", path = "bottom", gather = true},
    {map = "6,3", path = "bottom", gather = true},
    {map = "6,4", path = "bottom", gather = true},
    {map = "6,5", path = "bottom", gather = true},
    {map = "7,6", path = "top", gather = true},
    {map = "7,5", path = "top", gather = true},
    {map = "7,4", path = "top", gather = true},
    {map = "7,3", path = "top", gather = true},
    {map = "7,2", path = "top", gather = true},
    {map = "7,1", path = "right", gather = true},
    {map = "8,1", path = "bottom", gather = true},
    {map = "8,2", path = "bottom", gather = true},
    {map = "8,3", path = "bottom", gather = true},
    {map = "8,4", path = "bottom", gather = true},
    {map = "8,5", path = "bottom", gather = true},
    {map = "8,6", path = "right", gather = true},
    {map = "9,6", path = "top", gather = true},
    {map = "9,5", path = "right", gather = true},
    {map = "10,5", path = "right", gather = true},
    {map = "11,5", path = "bottom", gather = true},
    {map = "11,6", path = "bottom", gather = true},
    {map = "11,7", path = "bottom", gather = true},
    {map = "11,8", path = "left", gather = true},
    {map = "10,8", path = "left", gather = true},
    {map = "2,-2", path = "bottom"},
    {map = "2,-1", path = "bottom"},
    {map = "2,0", path = "bottom"},
    {map = "2,1", path = "bottom"},
    {map = "2,2", path = "bottom"},
    {map = "2,3", path = "bottom"},
    {map = "2,4", path = "bottom"},
    {map = "2,5", path = "bottom"},
    {map = "2,6", path = "bottom"},
    {map = "2,7", path = "right"},
    {map = "3,7", path = "right"},
}

function processMap()
    for index, actualMap in pairs(mapsWithChangeMap) do
        if (map:onMap(actualMap.map)) then
            if (type(actualMap.path) == "table") then
                if (not actualMap.toggle) then
                    actualMap.toggle = {}
                    for i = 1, #(actualMap.path) do
                        table.insert(actualMap.toggle, false)
                    end
                else
                    toggleTemp = false
                    for i = 1, #(actualMap.toggle) do
                        toggleTemp = actualMap.toggle[i]
                    end
                    if (toggleTemp) then
                        for i = 1, #(actualMap.toggle) do
                            actualMap.toggle[i] = false
                        end
                    end
                end
                for i, action in pairs(actualMap.path) do
                    if (not actualMap.toggle[i]) then
                        if (type(action) == "string") then
                            actualMap.toggle[i] = true
                            return map:changeMap(action)
                        elseif (type(action) == "number") then
                        actualMap.toggle[i] = true
                            return map:door(action)
                        elseif (type(action) == "function") then
                            actualMap.toggle[i] = true
                            return action()
                        end
                    end
                end
            else
                if (actualMap.path) then
                    return map:changeMap(actualMap.path)
                elseif (actualMap.door) then
                    if (type(actualMap.door) == "string") then
                        return map:door(tonumber(actualMap.door))
                    elseif (type(actualMap.door) == "number") then
                        return map:door(actualMap.door)
                    end
                elseif (actualMap.custom) then
                    return actualMap.custom()
                end
            end
        end
    end
end

function bank()
    banque = true
    return {
        {map = "2,7", path = "top"},
        {map = "2,6", path = "top"},
        {map = "2,5", path = "top"},
        {map = "2,4", path = "top"},
        {map = "2,3", path = "top"},
        {map = "2,2", path = "top"},
        {map = "2,1", path = "top"},
        {map = "2,0", path = "top"},
        {map = "2,-1", path = "top"},
        {map = "11,5", path = "left"},
        {map = "10,5", path = "left"},
        {map = "11,6", path = "left"},
        {map = "11,7", path = "left"},
        {map = "11,8", path = "left"},
        {map = "10,8", path = "left"},
        {map = "10,7", path = "left"},
        {map = "10,6", path = "left"},
        {map = "9,5", path = "left"},
        {map = "9,6", path = "left"},
        {map = "9,7", path = "left"},
        {map = "9,8", path = "left"},
        {map = "8,8", path = "left"},
        {map = "8,7", path = "left"},
        {map = "8,6", path = "left"},
        {map = "8,5", path = "left"},
        {map = "8,4", path = "left"},
        {map = "8,3", path = "left"},
        {map = "8,2", path = "left"},
        {map = "8,1", path = "left"},
        {map = "7,1", path = "left"},
        {map = "7,2", path = "left"},
        {map = "7,3", path = "left"},
        {map = "7,4", path = "left"},
        {map = "7,5", path = "left"},
        {map = "7,6", path = "left"},
        {map = "7,7", path = "left"},
        {map = "7,8", path = "left"},
        {map = "6,8", path = "left"},
        {map = "6,7", path = "left"},
        {map = "6,6", path = "left"},
        {map = "6,5", path = "left"},
        {map = "6,4", path = "left"},
        {map = "6,3", path = "left"},
        {map = "6,2", path = "left"},
        {map = "5,2", path = "left"},
        {map = "5,3", path = "left"},
        {map = "5,4", path = "left"},
        {map = "5,5", path = "left"},
        {map = "5,6", path = "left"},
        {map = "5,7", path = "left"},
        {map = "5,8", path = "left"},
        {map = "5,9", path = "left"},
        {map = "6,9", path = "left"},
        {map = "4,9", path = "left"},
        {map = "4,8", path = "left"},
        {map = "4,7", path = "left"},
        {map = "4,2", path = "left"},
        {map = "4,3", path = "left"},
        {map = "4,4", path = "left"},
        {map = "4,5", path = "left"},
        {map = "4,6", path = "left"},
        {map = "3,9", path = "left"},
        {map = "3,8", path = "left"},
        {map = "3,7", path = "left"},
        {map = "3,6", path = "left"},
        {map = "3,5", path = "left"},
        {map = "3,4", path = "left"},
        {map = "3,3", path = "left"},
        {map = "3,2", path = "left"},
        {map = "1,8", path = "right"},
        {map = "1,9", path = "right"},
        {map = "0,9", path = "right"},
        {map = "0,8", path = "right"},
        {map = "2,9", path = "top"},
        {map = "2,8", path = "top"},
        {map = "6,1", path = "left"},
        {map = "5,1", path = "left"},
        {map = "4,1", path = "left"},
        {map = "3,1", path = "left"},
        {map = "9,9", path = "top"},
        {map = "20,1", path = "bottom"},
        {map = "191104002", door = "288"}, --Devant banque Astrub--
        {map = "192415750", path = "409", custom = hiboux}, --Banque Astrub--
        {map = "54172457", door = "358"}, --Devant banque Frigost--
        {map = "54534165", path = "424", npcBank = true}, --Banque Frigost--
        {map = "147254", door = "383"}, --Devant banque Bonta--
        {map = "2885641", path = "424", npcBank = true}, --Banque Bonta--
        {map = "88081177", door = "216"}, --Devant banque Amakna--
        {map = "99095051", path = "410", npcBank = true}, --Banque Amakna--
        {map = "144931", door = "248"}, --Devant banque Brakmar--
        {map = "8912911", path = "424", npcBank = true}, --Banque Brakmar--
        {map = "90703872", door = "302"}, --Devant banque Sufokia --
        {map = "91753985", path = "494", npcBank = true}, --Banque Sufokia--
        {map = "155157", door = "355"}, --Devant banque Ottomaï--
        {map = "86511105", door = "452", npcBank = true}, --Banque Ottomaï--
        {map = "12580", door = "284"}, --Devant banque Pandala--
        {map = "8129542", path = "409", npcBank = true}, --Banque Pandala--
        {map = "73400323", door = "330"}, --Devant banque Montagne Koalak--
        {map = "84935175", path = "425", npcBank = true}, --Banque Montagne Koalak--
    }
end


function phenix()
    return {
    }
end

Ответы [ 2 ]

0 голосов
/ 05 марта 2020

В соответствии со структурой скрипта вы используете SnowBot или его производную. Я не знаю, как это работает, но есть мои наблюдения без знания фона.

Мое предположение, что эта часть кода вызывает рекурсию:

  elseif (actualMap.custom) then
    return actualMap.custom()
  end

actualMap.custom параметр оценивается как processMap в некоторых ситуациях и custom могут быть частью API, и механизм вызывает эту функцию в других обстоятельствах.

Чтобы отследить, если это создает некоторые проблемы, добавьте в начале processMap функцию:

global:printError("TRACK processMap: "....debug.traceback())

он должен отображать список вызовов стека, и если он будет длиннее каждый раз, эта функция создает вам проблемы.

Возможно, вы можете закомментировать return actualMap.custom() и проверить, помогает ли это , затем закомментируйте другие части и т. д.

На вашем месте я бы добавил еще несколько контрольных точек global:printError('Check ...'), чтобы проверить, работает ли он должным образом, или, может быть, какое-то действие выполнено несколько раз.

PS

Логическая ошибка:

   toggleTemp = false
   for i = 1, #(actualMap.toggle) do
     toggleTemp = actualMap.toggle[i]
   end

toggleTemp всегда будет значением последнего элемента

0 голосов
/ 05 марта 2020

Прежде всего, позвольте мне объяснить, что означает переполнение стека.

Википедия объясняет это так:

В программном обеспечении переполнение стека происходит, если указатель стека вызовов превышает границы стека. Стек вызовов может состоять из ограниченного объема адресного пространства, часто определяемого в начале программы. Размер стека вызовов зависит от многих факторов, включая язык программирования, архитектуру машины, многопоточность и объем доступной памяти. Когда программа пытается использовать больше места, чем доступно в стеке вызовов (то есть, когда она пытается получить доступ к памяти за пределами стека вызовов, что по сути является переполнением буфера), считается, что стек переполняется, что обычно приводит к program cra sh.

Другими словами: что-то в вашем скрипте постоянно добавляется в стек вызовов до тех пор, пока не переполнится.

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

Представьте себе скрипт, подобный следующему:

local function print()
    print "Foobar"
end
print()
print()

Вывод будет:

"Foobar"
"Foobar"

Но, что более важно, стек вызовов не будет увеличиваться, поскольку после обработки первой функции печати она удаляется из стека вызовов. Затем вызывается второй.

Теперь сравните его с этой функцией:

local function recursivePrint()
    print "Foobar"
    recursivePrint() -- Function calls itself, starting the recursion.
end
recursivePrint()

Вывод будет:

"Foobar"
"Foobar"
"Foobar"
"Foobar"
...
Stack-Overflow Error

Почему это происходит? Каждый раз, когда вызывается recursivePrint, он добавляется в стек вызовов и Foobar выводится на консоль. Но вместо удаления из стека вызовов добавляется и обрабатывается следующий recursivePrint.

Вы можете представить себе, что стек вызовов выглядит следующим образом:

recursivePrint()
    calls -> recursivePrint()
        calls -> recursivePrint()
            calls -> recursivePrint()
                calls -> recursivePrint()

Это продолжается до тех пор, пока граница стека не достигнута. Как только оно превышено, выдается ошибка.

Итак, как вы исправляете свой код?

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

Также обязательно используйте правильный хвост называет . На этой странице описана игра, похожая на вашу (если я правильно интерпретировал ваш код):

В качестве примера рассмотрим простую игру-лабиринт. В лабиринте есть несколько комнат, каждая из которых имеет до четырех дверей: север, юг, восток и запад. На каждом шаге пользователь вводит направление движения. Если в этом направлении есть дверь, пользователь идет в соответствующую комнату; в противном случае программа выводит предупреждение. Цель состоит в том, чтобы go из начальной комнаты в конечную комнату.

и, что еще более важно:

Без надлежащих вызовов на хвост, каждое движение пользователя будет создавать новый уровень стека. После некоторого количества ходов произойдет переполнение стека. При правильных конечных вызовах количество ходов, которые может сделать пользователь, не ограничено, поскольку каждый шаг фактически выполняет переход к другой функции, а не к обычному вызову.

Я вполне уверен, что это ваша актуальная проблема.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...