Крашит игру при долгой отрисовке списка

romanespit

Участник
Автор темы
53
23
Версия MoonLoader
.026-beta
Привет. Столкнулся с крашами в паре из своих скриптов, но так как крашит всю игру, а не только скрипт, не могу понять, с чем это связано до конца.
1753447076646.png

Код:
Crash at: 0x655F77F1: c0000005
EAX: 139
ECX: 2a423a10
EDX: 2a410280
EBX: 36
ESP: 177efc0
EBP: 2a4101c0
ESI: 2a466aa0
EDI: 2a466aa0
EIP: 655f77f1
Flags: 10206
ZF: false
CF: false
SF: false
OF: false
PF: true
Trace 0: 655f77f1 -> lua51.dll + 0x77F1
Trace 1: 65639325 -> lua51.dll + 0x49325
Trace 2: 657a9825 -> moonloader.asi + 0x119825
Trace 3: 656c0197 -> moonloader.asi + 0x30197
Trace 4: 65699bd9 -> moonloader.asi + 0x9BD9
Trace 5: 655f280d -> lua51.dll + 0x280D
Trace 6: 65617afb -> lua51.dll + 0x27AFB
Trace 7: 65617d07 -> lua51.dll + 0x27D07
Trace 8: 656176c0 -> lua51.dll + 0x276C0
Trace 9: 6561c3f9 -> lua51.dll + 0x2C3F9
Trace a: 6561c965 -> lua51.dll + 0x2C965
Trace b: 655f188f -> lua51.dll + 0x188F
Trace c: 5c785db6 -> d3d9.dll + 0x85DB6
Trace d: 6569b6dc -> moonloader.asi + 0xB6DC
Trace e: 656a6bcc -> moonloader.asi + 0x16BCC
Trace f: 6569488c -> moonloader.asi + 0x488C
Trace 10: 6784bd68 -> vorbisfile.dll + 0x1EBD68
Trace 11: 654262ad -> sampfuncs.asi + 0x362AD
Trace 12: 7f9b12 -> gta_sa.exe::__rwD3D9RasterShowRaster + 162
Trace 13: 658bb8e9 -> modloader.asi + 0x1B8E9
Trace 14: 658bfc02 -> modloader.asi + 0x1FC02
Trace 15: 658be267 -> modloader.asi + 0x1E267
Trace 16: 658c0246 -> modloader.asi + 0x20246
Trace 17: 658c013c -> modloader.asi + 0x2013C
Trace 18: 4aa0faf -> modloader.asi + 0x9F200FAF
Trace 19: 619b71 -> gta_sa.exe::_Z14RsEventHandler7RsEventPv + 11
Trace 1a: 748da0 -> gta_sa.exe::_WinMain + 690
Trace 1b: 658bfb94 -> modloader.asi + 0x1FB94
Trace 1c: 658bde46 -> modloader.asi + 0x1DE46
Trace 1d: 658bb83b -> modloader.asi + 0x1B83B
Trace 1e: 658bfbbb -> modloader.asi + 0x1FBBB
Trace 1f: 658be202 -> modloader.asi + 0x1E202
Trace 20: 658c07bb -> modloader.asi + 0x207BB
Trace 21: 658c0188 -> modloader.asi + 0x20188
Trace 22: 658bdf18 -> modloader.asi + 0x1DF18
Trace 23: 658bb83b -> modloader.asi + 0x1B83B
Trace 24: 658bfbbb -> modloader.asi + 0x1FBBB
Trace 25: 658be202 -> modloader.asi + 0x1E202
Trace 26: 658c07bb -> modloader.asi + 0x207BB
Trace 27: 658c0188 -> modloader.asi + 0x20188
Trace 28: 8246f1 -> gta_sa.exe::__CrtMain + 181
Trace 29: 75327ba9 -> kernel32.dll + 0x17BA9
Trace 2a: 770dc3ab -> ntdll.dll + 0x6C3AB
Trace 2b: 770dc32f -> ntdll.dll + 0x6C32F
Last opcodes: 0248 0248 0248 0248 0248 052C 09BA 0470 077E 077E
Last created vehicle: 65535(65535)
Last prerendered vehicle: 65535
Last removed model: 11412
Last removed car: 65535
Last removed ped: 221
Last removed object: 1239
Last created object: 65535(65535)
Last GetColModel: 1684
Last anim group: 54
Last anim id: 3
Last anim current time: 0
Last anim total time: 1.5
Last CSprite2d::Draw texture:radar_north
CRenderer lists:
    CRenderer::ms_nNoOfVisibleLods = 132
    CRenderer::ms_nNoOfVisibleEntities = 194
    CRenderer::ms_nNoOfVisibleSuperLods = 0
    CRenderer::ms_nNoOfInVisibleEntities = 11

Из похожего - у обоих скриптов используются циклы для отрисовки и childы. Для ловли удалил вообще все лишнее и оставил только один child - крашит. Из интересного, что крашит не мгновенно, а спустя время, будто где-то переполняется память или что-то такое, но я не понимаю что. На примере второго кода ограничивал массив данных до 10 элементов - ситуация та же, уже не знаю, куда копать.
Первый:
imgui.OnFrame(function() return WinState[0] end, -- Main Frame
    function(player)
        imgui.SetNextWindowPos(imgui.ImVec2(sx/2, 500), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.Begin(u8(SCRIPT_TITLE), WinState, imgui.WindowFlags.AlwaysAutoResize+imgui.WindowFlags.NoCollapse+imgui.WindowFlags.NoTitleBar)
        if imgui.BeginChild('##scriptlist', imgui.ImVec2(200, 400), true) then
            imgui.CenterTextDisabled(u8'Основные')
            for k,v in pairs(ScriptInfo) do
                if not v.lua_url:find("extraScripts") then
                    if not k:find("NespitManager") then         
                        if not IsScriptInstalled(k) then imgui.Indent(15) end
                        if imgui.advBanner((IsScriptInstalled(k) and fa.CHECK.." " or "")..fa.FILE_CODE..u8(" "..k)..(v.label ~= "" and " "..fa.STAR or ""), imgui.ImVec2(0, 0), 2, (v.label ~= "" and u8(v.label) or nil)) then
                            SELECTEDSCRIPT = k
                            if IsScriptInstalled(k) then
                                selected_scr = find_script_by_path(dirml..'\\'..SELECTEDSCRIPT..'.lua')
                            else selected_scr = nil end
                            
                        end               
                        if not IsScriptInstalled(k) then imgui.Indent(-15) end
                    end
                end
            end
            imgui.CenterTextDisabled(u8'Дополнительные')
            for k,v in pairs(ScriptInfo) do
                if v.lua_url:find("extraScripts") then
                    if not IsScriptInstalled(k) then imgui.Indent(15) end
                    if imgui.advBanner((IsScriptInstalled(k) and fa.CHECK.." " or "")..fa.FILE_CODE..u8(" "..k)..(v.label ~= "" and " "..fa.STAR or ""), imgui.ImVec2(0, 0), 2, (v.label ~= "" and u8(v.label) or nil)) then
                        SELECTEDSCRIPT = k
                        if IsScriptInstalled(k) then
                            selected_scr = find_script_by_path(dirml..'\\'..SELECTEDSCRIPT..'.lua')
                        else selected_scr = nil end
                        
                    end               
                    if not IsScriptInstalled(k) then imgui.Indent(-15) end
                end
            end
            imgui.EndChild()
        end
        imgui.End()
    end
)
На примере второго скрипта выяснил, что пока не отрисовываешь часть с циклом - можно сидеть с открытым скриптом сколько угодно, краша не будет. Как только отрисовываешь - идет "обратный отсчет" и краш неизбежен
Второй:
if imgui.BeginTabBar('Tabs') then
                        if #result_sell > 0 then
                            if imgui.BeginTabItem(u8'Продают') then
                                imgui.Columns(4)
                                imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.5)
                                imgui.CenterColumnText(u8'Товар')
                                imgui.NextColumn()
                                imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.25)
                                imgui.CenterColumnText(u8'Цена')
                                imgui.NextColumn()
                                imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.15)
                                imgui.CenterColumnText(u8'Сколько')
                                imgui.NextColumn()
                                imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.1)
                                imgui.CenterColumnText(fa.CIRCLE_INFO)
                                imgui.Columns(1)
                                imgui.Separator()
                                if imgui.BeginChild('##resultsell', imgui.ImVec2(imgui.GetWindowWidth()*0.98, 350), true) then
                                    for i, item in ipairs(result_sell) do
                                        imgui.Columns(4)
                                        imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.5)
                                        imgui.CenterColumnText(u8(item.name))
                                        imgui.NextColumn()
                                        imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.25)
                                        imgui.CenterColumnText(u8("VC$")..convertToPriceFormat(item.price))
                                        imgui.NextColumn()
                                        imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.15)
                                        imgui.CenterColumnText(tostring(item.count))
                                        imgui.NextColumn()
                                        imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.1)
                                        if imgui.Button(item.lavka..'##sell'..i) then if isViceCity() then sampSendChat('/findilavka '..item.lavka) else sms("Для поиска лавки нужно быть на сервере Vice City") end end
                                        if imgui.IsItemHovered() and isViceCity() then imgui.SetTooltip(u8'Нажмите, чтобы найти лавку') end
                                        imgui.Columns(1)
                                        imgui.Separator()
                                    end
                                    imgui.EndChild()
                                end
                                imgui.EndTabItem()
                            end
                        end
                        if #result_buy > 0 then
                            if imgui.BeginTabItem(u8'Покупают') then
                                imgui.Columns(4)
                                imgui.CenterColumnText(u8'Товар') imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.5)
                                imgui.NextColumn()
                                imgui.CenterColumnText(u8'Цена') imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.25)
                                imgui.NextColumn()
                                imgui.CenterColumnText(u8'Сколько') imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.15)
                                imgui.NextColumn()
                                imgui.CenterColumnText(fa.CIRCLE_INFO) imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.1)
                                imgui.Columns(1)
                                imgui.Separator()
                                if imgui.BeginChild('##resultbuy', imgui.ImVec2(imgui.GetWindowWidth()*0.98, 350), true) then
                                    for i, item in ipairs(result_buy) do
                                        imgui.Columns(4)
                                        imgui.CenterColumnText(u8(item.name)) imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.5)
                                        imgui.NextColumn()
                                        imgui.CenterColumnText(u8("VC$")..convertToPriceFormat(item.price)) imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.25)
                                        imgui.NextColumn()
                                        imgui.CenterColumnText(tostring(item.count)) imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.15)
                                        imgui.NextColumn()
                                        if imgui.Button(item.lavka..'##buy'..i) then if isViceCity() then sampSendChat('/findilavka '..item.lavka) else sms("Для поиска лавки нужно быть на сервере Vice City") end end
                                        if imgui.IsItemHovered() and isViceCity() then imgui.SetTooltip(u8'Нажмите, чтобы найти лавку') end
                                        imgui.SetColumnWidth(-1, imgui.GetWindowWidth()*0.1)
                                        imgui.Columns(1)
                                        imgui.Separator()
                                    end
                                    imgui.EndChild()
                                end
                                imgui.EndTabItem()
                            end
                        end
                        imgui.EndTabBar()
                    end
Может кто-то из старичков сталкивался с таким и знает то, чего не знаю я? Всю голову сломал, буду рад любым советам. За годный совет могу даже копейку зарядить ибо всю башку сломал и идей нет 🥹

Получил больше информации: Засунул логгер collectgarbage("count") в отрисовку и вижу, что память утекает (причина пока не ясна). Закрыл костылем
collectgarbage("collect") в начале отрисовки окна. Насколько это хуевый костыль, знает кто? Или есть идеи из-за чего она вытекает?
 
Последнее редактирование:

wojciech?

Известный
Проверенный
435
394
Без полного кода могу предложить только такие оптимизации:
Lua:
local function DrawScriptInfo(scripts, caption, mode)
    imgui.CenterTextDisabled(caption)
    for k, v in pairs(scripts) do
        -- один раз определяем тип скрипта
        if not v.mode then
            v.mode = (k:find("NespitManager") or v.lua_url:find("extraScripts")) and 2 or 1
        end

        if mode == v.mode then
            -- один раз подготавливаем строчки
            if not v.fmt_one then
                if v.label ~= "" then
                    v.fmt_one = ("%s %s %s"):format(fa.FILE_CODE, u8(k), fa.STAR)
                    v.u8label = u8(v.label)
                else
                    v.fmt_one = ("%s %s"):format(fa.FILE_CODE, u8(k))
                end
            end

            -- один раз определяем установлен ли скрипт и отрисовываем в зависимости от этого содержимое
            if IsScriptInstalled(k) then
                if imgui.advBanner(("%s %s"):format(fa.CHECK, v.fmt_one), imgui.ImVec2(0, 0), 2, v.u8label) then
                    SELECTEDSCRIPT = k
                    selected_scr = find_script_by_path(("%s\\%s.lua"):format(dirml, SELECTEDSCRIPT))
                end
            else
                imgui.Indent(15)
                if imgui.advBanner(f.fmt_one, imgui.ImVec2(0, 0), 2, v.u8label) then
                    SELECTEDSCRIPT = k
                    selected_scr = nil
                end
                imgui.Indent(15)
            end
        end
    end
end

imgui.OnFrame(function() return WinState[0] end,
function()
    imgui.SetNextWindowPos(imgui.ImVec2(sx/2, 500), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    imgui.Begin(u8(SCRIPT_TITLE), WinState, imgui.WindowFlags.AlwaysAutoResize + imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoTitleBar)
        imgui.BeginChild("##scriptlist", imgui.ImVec2(200, 400), true)
            DrawScriptInfo(ScriptInfo, u8"Основные", 1)
            DrawScriptInfo(ScriptInfo, u8"Дополнительные", 2)
        imgui.EndChild()
    imgui.End()
end)

collectgarbage("collect") в начале отрисовки окна. Насколько это хуевый костыль, знает кто?
Очень сомнительно

Или есть идеи из-за чего она вытекает?
Скорее всего бесконечные временные объекты на каждом кадре, которые не собирает сборщик мусора
 

Похожие темы

  1. У
    • Закрыта
    • Вопрос
    Ответы
    5
    Просмотры
    1K
    Помощь
    Удалённый пользователь 140342
    У