XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Jass
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Закрытая тема
 
DioD

offline
Опыт: 45,134
Активность:
Дело в том, что так делают все, кеш не высвобождается сам по себе воообще, я долго думал зачем высвобождать кеш а потом провёл тесты, у меня сохранялись все значения...
Таким хитрым образом можно делать лог карты в которые будет включена функция лога, таким образом модно запоминать все карты в которые играл человек...
Старый 26.07.2006, 15:19
Joes
Having 24/7 party.
offline
Опыт: 210
Активность:
Могу предположить следующее.
Вводная:
  1. Любая сущность в War3 это объект.
  2. У объекта есть refcount.
Refcount, он же счетчик ссылок, просто переменная, которая содержит количество ссылок на данный объект. Грубо говоря, когда 1 переменная ссылается на объект, то там будет 1. Как только в переменную записали null, она перестала ссылаться на объект, refcount стал 0, объект прибили.
Теперь, что такое SCV - использование ассоциативного массива для связывания данных с объектом через использование хака, который конвертирует хендл объекта в его числовое значение.
Это число хоть и хранит некое значение связанное с объектом, но никак не увеличивает refcount оного (так как вообще левый тип данных и с объектами вообще никак не связан).
Объект убивают, но числовое значение (хендл, указатель, как кому удобнее) в кеше все еще висит. Вот и получается полная аналогия с висящими указателями. Кстати, тоже самое можно сделать и без кеша - просто переменной типа int присвойте H2I значение, объекту присвойте null, а потом попытайтесь из переменной получить объект и что то с ним сделать.
Как решать? Правильнее всего отлавливать убийство объектов и как то на это реагировать (подчищать кеш, как минимум).
Второй вариант - всегда следить где идут убийства предметов (присвоение null) и делать подчистку кеша там же.
Старый 26.07.2006, 17:43
Sergey
Старейший
offline
Опыт: 44,363
Активность:
Ну, не совсем так. Я имею ввиду ситуацию, когда человек играет, затем выходит из игры. При этом, как ни странно, иногда в памяти компьютера сохраняются данные кеша. При запуске новой игры всплывают значения из старой. Причем ничего не помогает - идут сплошные глюки. Пару раз я попадал на такой баг. Потом начал использовать такой код:
Create a game cache from SCV.w3v
Clear (Last created game cache)
Create a game cache from SCV.w3v
Set cache = (Last created game cache)
Баг больше не возникал (т.к. даже если что-то оставалось от прошлой игры, кеш все равно обнулялся полностью).
На других картах я подобных конструкция не замечал. Возможно, что баг имел место только на моем компьютере.
Старый 26.07.2006, 17:43
Joes
Having 24/7 party.
offline
Опыт: 210
Активность:
Цитата:
Сообщение от DioD
Таким хитрым образом можно делать лог карты в которые будет включена функция лога, таким образом модно запоминать все карты в которые играл человек...

Это ж только для single-player, я не ошибаюсь?
Старый 26.07.2006, 17:44
DioD

offline
Опыт: 45,134
Активность:
Кеш это ПУЛ, в нём данные остаются до выгрузки варкрафта, то что тут описал Sergey общеизвестный факт, но данные сохраняются независимо от того синг или мультиплэер, просто они не пишутся на диск, можно очень хитро поиграв в какуюнить карту запустить карту с эксплойтом в сингле и сохранить весь кеш на диск... ну не знаю зачем это надо, но так теоритически можно сделать, практически это никому не надо...
Старый 26.07.2006, 17:54
Joes
Having 24/7 party.
offline
Опыт: 210
Активность:
Я имел в виду именно сохранение данных на винт.
Старый 26.07.2006, 19:00
DioD

offline
Опыт: 45,134
Активность:
Ну сохранение данных на винт можно устроить только на своём компе
Старый 26.07.2006, 19:38
Toadcop

offline
Опыт: 54,313
Активность:
Sergey а я и не писал что кеш глючит ! я написал что это в принципе Глюк Вара ! и кстати если что то сделать с пустотой то ты поток убъешь ! и будет не хилая утечка ! смыл вот короче карта
мой ТРС там я дебуг сообщений написал смотрите и есть триггер аналог который работает отлично !

т.е. новая версия ТРС вот http://xgm.guru/forum/attachment.php?attachmentid=7603


Sergey и еще то ты реально не тот БАГ нашёл то что ты нашёл это не баг а просто ламерство юзера ! + конечно я про совсем про другое там от юзера зависит только как он обращаетьса с данными или хранит в числовом виде или в прямом ! кстати я подумал что может по ходу игры Вар вообще просто изменяет хендл объекта и вся система РБ накрываетьса и это ВПОЛНЕ РЕАЛЬНО !

Отредактировано DioD, 01.08.2006 в 21:16.
Старый 27.07.2006, 14:53
B100D E1F
Scarecrow
offline
Опыт: 4,719
Активность:
Блиин вы меня напугали! Только-только 2 написанных на жассе моих нупских спелла, с которыми я провозился дофига времени, написанные на рб+кэш(СКВ) летят фтопку! Жалко блин так...
Старый 28.07.2006, 20:44
DioD

offline
Опыт: 45,134
Активность:
Если написаны правильно то не летят...
Старый 28.07.2006, 21:07
Toadcop

offline
Опыт: 54,313
Активность:
DioD а я вообще юникальное решения для юнитов и шмота предумал ! =) вот еще бы к остальным типам и РБ не нужно !
Старый 04.08.2006, 14:47
exploder
iOS zealot
offline
Опыт: 19,394
Активность:
Toadcop, может быть в твоем случает все дело в таймере? В его удалении, тоже забавный глюк, может бы ты не видел: http://www.wc3jass.com/viewtopic.php?t=2091

Потом ошибка может возникать из-за этого участка кода:
Код:
function Trig_Cleaner_GOVNO_Conditions takes nothing returns boolean
    return not IsUnitType(GetDyingUnit(),UNIT_TYPE_HERO)
endfunction

Смотри: http://www.wc3jass.com/viewtopic.php?t=2370. В boolexpr, тоже есть баг, а именно в резульате возврашаемом IsUnitType...

Заменив код сбойного тригерра на такой:
Код:
function Trig_Cleaner_GOVNO_Conditions takes nothing returns boolean
    return (IsUnitType(GetDyingUnit(),UNIT_TYPE_HERO) != true)
endfunction

function CleanDeadUnits takes nothing returns nothing
    local timer t=GetExpiredTimer()
    local integer i=Modulo(h2i(t),8192)
    local unit u=i2u(udg_DeadUnits[i]) //GetStoredInteger(udg_cache,I2S(h2i(t)),"unit"))
if GetStoredInteger(udg_cache,I2S(h2i(t)),"tmr")!=h2i(t) then
    call echo("|cffFF4444Wrong Timer Id !|r old id - |r"+I2S(GetStoredInteger(udg_cache,I2S(h2i(t)),"tmr"))+" new id - "+I2S(h2i(t)))
endif
if GetUnitUserData(u)!=0 then
    call echo("|cff5555ccREMOVE UNIT WITH USER DATA ! ERROR !|r")
endif
  if u!=null and GetUnitState(u,UNIT_STATE_LIFE)<=0 and not IsUnitLoaded(u) then
    //call SetUnitX(u,0)
    //call SetUnitY(u,0)
    call RemoveUnit(u)
  elseif GetUnitState(u,UNIT_STATE_LIFE)>0 then
    call echo("|cffaa6600UNIT HAVE HP !!!")
  elseif u!=null then
    call echo("|cffaa6600UNIT = NULL !!!")
  endif
    //call DestroyTimer(t)
    set udg_DeadUnits[i]=0
    //set t=null
    //set u=null
endfunction

function Trig_Cleaner_GOVNO_Actions takes nothing returns nothing
    local timer t=CreateTimer()
    call StoreInteger(udg_cache,I2S(h2i(t)),"tmr",h2i(t))
// Can use cache ->
    //call StoreInteger(udg_cache,I2S(h2i(t)),"unit",h2i(GetTriggerUnit()))
if udg_DeadUnits[Modulo(h2i(t),8192)]==0 then
    set udg_DeadUnits[Modulo(h2i(t),8192)]=h2i(GetTriggerUnit())
else
    call echo("|cff00ff00 THIS SLOT ALREADY USED !")
endif
    call TimerStart(t,20,false,function CleanDeadUnits)
    //set t=null
endfunction

//===========================================================================
function InitTrig_CleanerBUGED takes nothing returns nothing
    set gg_trg_CleanerBUGED = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_CleanerBUGED, EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(gg_trg_CleanerBUGED, Condition( function Trig_Cleaner_GOVNO_Conditions))
    call TriggerAddAction(gg_trg_CleanerBUGED, function Trig_Cleaner_GOVNO_Actions)
endfunction

Я заставил его вполне сносно работать. Еднисвенные сообщения, которые вылетали, были о том что юнит имеет хиты...

Закоментировал обнуления, заменил булекспр... Тут не глюк кэша, а глюк с обнулением переменных, ведь близзы сами никогда обнуление не юзали, вот и не протестили, возможны глюки...
Старый 04.08.2006, 21:43
Toadcop

offline
Опыт: 54,313
Активность:
Цитата:
Я заставил его вполне сносно работать. Еднисвенные сообщения, которые вылетали, были о том что юнит имеет хиты...

Закоментировал обнуления, заменил булекспр... Тут не глюк кэша, а глюк с обнулением переменных, ведь близзы сами никогда обнуление не юзали, вот и не протестили, возможны глюки...
а почему если я не перевожу юнита в инт и передаю ЧЕРЕЗ этот же таймер как юнита через массив !!! ТО ГЛЮКОВ НЕТУ !? и вообще у тебя старая версия ТРС закачай новую ! и если ты такой крутой посмотри сюда ! http://wc3campaigns.net/showthread.php?t=85984 и может еще что то... =)
Старый 08.08.2006, 15:33
Toadcop

offline
Опыт: 54,313
Активность:
вот ссыль на оригинал и т.д. http://wc3campaigns.net/showthread.php?t=85984
Код:
function H2I takes handle h returns integer
    return h
    return 0
endfunction

function NothingAction takes nothing returns nothing
endfunction

function CreateAction takes nothing returns nothing
    call CreateTrigger() //Create any object
endfunction

function RunStuff takes nothing returns nothing
local integer i=0

    call TriggerSleepAction(0.00) //This wait action is needed for the bug to happen
    call TriggerSleepAction(0.00)
    call TriggerSleepAction(0.00)
    call TriggerSleepAction(0.00) // can have any count of Sleeps. will increase the FATAL index count =)
    set i=1
    set udg_locus=null
    loop
        exitwhen i > 10
        set udg_loc[i]=Location(GetRandomReal(-100,100),GetRandomReal(-100,100))
        call BJDebugMsg("X = "+R2S(GetLocationX(udg_loc[i]))+"  "+"Y = "+R2S(GetLocationY(udg_loc[i])))
        if udg_loc[i]==udg_locus then
            call BJDebugMsg("FATALatindex:"+I2S(i)+";"+I2S(H2I(udg_loc[i])))
        else
            call BJDebugMsg("Index:"+I2S(i)+";"+I2S(H2I(udg_loc[i])))
        endif
        set udg_locus=udg_loc[i]
        set i=i+1
    endloop
    call BJDebugMsg("Ended")
endfunction


function Trig_Test_Actions takes nothing returns nothing
local integer i=0
    call TriggerExecute(udg_t[5])
    call DestroyTrigger(GetTriggeringTrigger())  //Without this call, the bug won't happen
    call TriggerSleepAction(0.00)
    call TriggerSleepAction(0.00)
    call TriggerSleepAction(0.00)
    loop
        exitwhen i > 10
        set udg_loc[i]=Location(GetRandomReal(-100,100),GetRandomReal(-100,100))
        call BJDebugMsg("X = "+R2S(GetLocationX(udg_loc[i]))+"  "+"Y = "+R2S(GetLocationY(udg_loc[i])))
        if udg_loc[i]==udg_locus then
            call BJDebugMsg("FATALatindex:"+I2S(i)+";"+I2S(H2I(udg_loc[i])))
        else
            call BJDebugMsg("Index:"+I2S(i)+";"+I2S(H2I(udg_loc[i])))
        endif
        set udg_locus=udg_loc[i]
        set i=i+1
    endloop
    call BJDebugMsg("Ended")

// I don't have any Bugs =)
// The testing will be continued...
endfunction

//===========================================================================
function InitTrig_Test takes nothing returns nothing
    set gg_trg_Test = CreateTrigger(  )
    set udg_t[0]= CreateTrigger(  )
    set udg_t[1]= CreateTrigger(  )
    call TriggerAddAction( udg_t[0], function NothingAction )
    call TriggerAddAction( udg_t[1], function CreateAction )
    set udg_t[5]=CreateTrigger()
    call TriggerAddAction(udg_t[5],function RunStuff)
    call TriggerRegisterPlayerChatEvent( gg_trg_Test, Player(0), "test", true )
    call TriggerAddAction( gg_trg_Test, function Trig_Test_Actions )
endfunction

вот посмотрите =) короче будет все ОК ! а потом удалите вот это код после call DestroyTrigger(GetTriggeringTrigger()) //Without this call, the bug won't happen.
до конца функции. и увидите счастье про РБ =) то что локации будут иметь одинаковый хандле индекс но будут полностью рабочии ! вот РБ говно ! точнее Вар а может имено и РБ незнаю =)
еще попробуйте разное количество call TriggerSleepAction(0.00) в перед созданием локацийй и т.д. =)

желаю удачи...

Отредактировано DioD, 10.08.2006 в 20:39.
Старый 10.08.2006, 19:52
exploder
iOS zealot
offline
Опыт: 19,394
Активность:

Я там был, прочитал весь топик. Весьма интересно. Но на момент того как я читал не единого докозательства о глючности кэша не было найдено, а Векс, стамит там всех по полной =))
Старый 12.08.2006, 13:16
DioD

offline
Опыт: 45,134
Активность:
Векс всё делает правильно...
Надо на кампы и сич чаще ходить
Старый 12.08.2006, 20:53
exploder
iOS zealot
offline
Опыт: 19,394
Активность:
DioD, против Векса я ничего против не имею =)) Я имею ввиду он вас стамит... а порой просто не понимает ваш корявый английский...
Старый 15.08.2006, 15:14
Toadcop

offline
Опыт: 54,313
Активность:
Цитата:
корявый английский...
мой особенно =) да мы кстати первый пришли к правильному выводу =) ! буржуи чуть тугие ! чёто умное хотел сказать ... блин забыл =)
Старый 28.08.2006, 17:18
DotA_DR

offline
Опыт: 103
Активность:
Цитата:
если условие и действие не "фиксировать" в переменной (или чё нибудь еще) то в принципе уже
происходит утечка 2-ух хандлов (адресов) вот почему люди не сталкиваютьса с такой проблемой которую я описал !

интерестно, можно по подробнее?
ведь если "хандлы" не зафиксированы, то значит они могут быть переиспользованы, в чём тут утечка?
на сколько я знаю функции для удаления условий и действий нет

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

думаю можно придерживаться следующих правил и всё будет нормально:
1. В любом случае очищать локальные переменные типа handle
2. Если объект создаётся и удаляется в одной функции(потоке) (в том же вызове), и с ним работают в других потоках, то должен быть хотя бы 1 указатель на объект (обычно это выполняется указатель храниться в локальной переменной)
3. Если объект создаётся, но остаётся после завершения функции и планируется работа с ним, то необходимо сохранять этот указатель в некий глобальный пул (тут пока нет определённости: переменная, массив что-то ещё), потом при удалении объект удалять указатель из пула.
Старый 30.08.2006, 14:04
DioD

offline
Опыт: 45,134
Активность:
Действие и условие сохраняется форева и даже после удаления тригера будет существовать.
Через H2I и кеш его можно подключить к другому тригеру.
Кстати этот метод более гуманен, так как не требует постоянного создания и удаления объектов.
Старый 30.08.2006, 14:30
Закрытая тема

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

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

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 21:45.