New Leak Found: Keeping references to destroyed objects.

Jesus4Lyf

Good Idea™
Reaction score
397
These are memory leaks (but not handle id leaks). You must check the process list to see it leak.
Credits to Troll-Brain for finding the original leak.

This leaks:
JASS:
library Test initializer init

globals
    private group G1
    private group G2
    private group GROUP=CreateGroup()
    private trigger Trig
endglobals

private function Actions takes nothing returns nothing
    call BJDebugMsg("Start")
    call EnableTrigger(Trig)
    call TriggerSleepAction(10.)
    call DisableTrigger(Trig)
    call BJDebugMsg("End")
endfunction

private function DoTheTest takes nothing returns nothing
    //call BJDebugMsg("run")
    set G1=null // With or without this line.
    set G1=CreateGroup()
    call DestroyGroup(G1)
endfunction

private function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    set Trig = CreateTrigger()
    
    call TriggerRegisterTimerEvent(Trig,0.0,true)
    call TriggerAddAction(Trig,function DoTheTest)
    call DisableTrigger(Trig)
    
    call TriggerRegisterPlayerEventEndCinematic(trig,Player(0))
    call TriggerAddAction(trig, function Actions)
endfunction

endlibrary
In fact, even this leaks:
JASS:
library Test initializer init

globals
    private group G1
    private group G2
    private group GROUP=CreateGroup()
    private trigger Trig
endglobals

private function Actions takes nothing returns nothing
    call BJDebugMsg("Start")
    call EnableTrigger(Trig)
    call TriggerSleepAction(10.)
    call DisableTrigger(Trig)
    call BJDebugMsg("End")
endfunction

globals
    boolean k=false
endglobals

private function DoTheTest takes nothing returns nothing
    //call BJDebugMsg("run")
    if k then
        set G1=null
    else
        set G1=CreateGroup()
        call DestroyGroup(G1)
    endif
    set k = not k
endfunction

private function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    set Trig = CreateTrigger()
    
    call TriggerRegisterTimerEvent(Trig,0.01,true)
    call TriggerAddAction(Trig,function DoTheTest)
    call DisableTrigger(Trig)
    
    call TriggerRegisterPlayerEventEndCinematic(trig,Player(0))
    call TriggerAddAction(trig, function Actions)
endfunction

endlibrary
This does not leak:
JASS:
library Test initializer init

globals
    private group G1
    private group G2
    private group GROUP=CreateGroup()
    private trigger Trig
endglobals

private function Actions takes nothing returns nothing
    call BJDebugMsg("Start")
    call EnableTrigger(Trig)
    call TriggerSleepAction(10.)
    call DisableTrigger(Trig)
    call BJDebugMsg("End")
endfunction

private function DoTheTest takes nothing returns nothing
    //call BJDebugMsg("run")
    set G1=CreateGroup()
    call DestroyGroup(G1)
    set G1=null
endfunction

private function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    set Trig = CreateTrigger()
    
    call TriggerRegisterTimerEvent(Trig,0.0,true)
    call TriggerAddAction(Trig,function DoTheTest)
    call DisableTrigger(Trig)
    
    call TriggerRegisterPlayerEventEndCinematic(trig,Player(0))
    call TriggerAddAction(trig, function Actions)
endfunction

endlibrary
What's the exact cause? Discuss. I will update this post as conclusions are reached and verified.

This is a minor leak.

Conclusion:
Not allowing a handle id to be recycled immediately after destruction causes a memory leak.
 
I have a new conclusion. We know that the handle id recycler will pick up a handle at any point after it has been destroyed, when its reference count hits 0.

Well, it seems if that is not immediately after it is destroyed, then it causes a leak.

I conclude this because setting the variable to "GROUP" (a constant group) also stops the leak.

Edit: Yep.
Does not leak:
JASS:
library Test initializer init

globals
    private group G1
    private group G2
    private group GROUP=CreateGroup()
    private trigger Trig
endglobals

private function Actions takes nothing returns nothing
    call BJDebugMsg("Start")
    call EnableTrigger(Trig)
    call TriggerSleepAction(10.)
    call DisableTrigger(Trig)
    call BJDebugMsg("End")
endfunction

private function OtherTest takes nothing returns nothing
    local group g=CreateGroup()
    call DestroyGroup(g)
    set g=null
    call TriggerSleepAction(0)
endfunction

private function DoTheTest takes nothing returns nothing
    //call BJDebugMsg("run")
    call OtherTest.execute()
endfunction

private function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    set Trig = CreateTrigger()
    
    call TriggerRegisterTimerEvent(Trig,0.0,true)
    call TriggerAddAction(Trig,function DoTheTest)
    call DisableTrigger(Trig)
    
    call TriggerRegisterPlayerEventEndCinematic(trig,Player(0))
    call TriggerAddAction(trig, function Actions)
endfunction

endlibrary
Does leak:
JASS:
library Test initializer init

globals
    private group G1
    private group G2
    private group GROUP=CreateGroup()
    private trigger Trig
endglobals

private function Actions takes nothing returns nothing
    call BJDebugMsg("Start")
    call EnableTrigger(Trig)
    call TriggerSleepAction(10.)
    call DisableTrigger(Trig)
    call BJDebugMsg("End")
endfunction

private function OtherTest takes nothing returns nothing
    local group g=CreateGroup()
    call DestroyGroup(g)
    call TriggerSleepAction(0)
    set g=null
endfunction

private function DoTheTest takes nothing returns nothing
    //call BJDebugMsg("run")
    call OtherTest.execute()
endfunction

private function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    set Trig = CreateTrigger()
    
    call TriggerRegisterTimerEvent(Trig,0.0,true)
    call TriggerAddAction(Trig,function DoTheTest)
    call DisableTrigger(Trig)
    
    call TriggerRegisterPlayerEventEndCinematic(trig,Player(0))
    call TriggerAddAction(trig, function Actions)
endfunction

endlibrary
 
I still don't see why you would want to destroy a global group, but it is probably an example that applies to handles in general?
 
So the conclusion is: Even globals have to be nulled after destruction.

One question: Does this leak? If yes, then globals have to be nulled immediately and not only inside the same instance.

JASS:

set G1 = CreateGroup()
call DestroyGroup(G1)
call DoNothing()
set G1 = null
 
This also leaks (demo using hashtables):
JASS:
library Test initializer init

globals
    private group G1
    private group G2
    private group GROUP=CreateGroup()
    private trigger Trig
    private hashtable H=InitHashtable()
endglobals

private function Actions takes nothing returns nothing
    call BJDebugMsg("Start")
    call EnableTrigger(Trig)
    call TriggerSleepAction(10.)
    call DisableTrigger(Trig)
    call BJDebugMsg("End")
endfunction

private function DoTheTest takes nothing returns nothing
    call SaveGroupHandle(H,0,0,CreateGroup())
    call DestroyGroup(LoadGroupHandle(H,0,0))
endfunction

private function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    set Trig = CreateTrigger()
    
    call TriggerRegisterTimerEvent(Trig,0.0,true)
    call TriggerAddAction(Trig,function DoTheTest)
    call DisableTrigger(Trig)
    
    call TriggerRegisterPlayerEventEndCinematic(trig,Player(0))
    call TriggerAddAction(trig, function Actions)
endfunction

endlibrary
This does not leak (hashtables):
JASS:
private function DoTheTest takes nothing returns nothing
    call SaveGroupHandle(H,0,0,CreateGroup())
    call DestroyGroup(LoadGroupHandle(H,0,0))
    call SaveGroupHandle(H,0,0,GROUP)
endfunction

Neither does this:
JASS:
private function DoTheTest takes nothing returns nothing
    call SaveGroupHandle(H,0,0,CreateGroup())
    call DestroyGroup(LoadGroupHandle(H,0,0))
    call RemoveSavedHandle(H,0,0)
endfunction

>One question: Does this leak? If yes, then globals have to be nulled immediately
No, it does not (tested). But remember, nulling after a wait does (if the handle is removed during the wait).

So the conclusion is solid?
 
Tested. Setting a variable(contains destroyed value) to a new value will cause leaking.
 
Nay, Blizzard only fixes things that affect their income. Virus maps, yeah, suing could happen there. But a minor memory leak that people found out about eight years later? I don't think so.
 
Then why did they fix local masking? I can't see how that would affect their income.
 
Actually, according to Vexorian, local masking works perfectly now. ( link )

Noone really knows what Blizzard is doing and why...
 
>Then why did they fix local masking?

Because apparently typecasting could be done via shadowing. So Blizzard decided to fixit. Or something.
 
I guess that at least (partially) explains the slow memory increases of supposedly leak free maps that aren't increasing in active object count.

On the plus side, these leaks are tiny and generally preventable.
 
Oh hey look, a new leak...
Just another thing I need to learn how to fix. OH WELL.
 
Oh hey look, a new leak...
Just another thing I need to learn how to fix. OH WELL.
It's not that hard, just set to null the handle variable just after you have destroyed the handle, or flush gamecache/hashtable if you used it instead of a variable.

According to Jesus4Lyf you might can do it after few lines of code without waits, but i recommend to set to null in the line just below the handle destruction, just to be sure, at least it's more likely you won't forget it.
 
Yeah, well... It's still another thing to remember. And I'm really bad at remembering...
 
If you just recycle what can be recycled in a practical manner you should be fine. That's more efficient anyway than create and destroy, and results in cleaner end code (ie no need to null anything). Global group + GroupClear for instant-use groups, GroupUtils or some other recycler for other groups, TU and maybe T32 for timers depending on what you are doing/need, etc.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Varine Varine:
    It's actually remarkably easy to make mayonnaise though. Fun fact, it USED to kind of be a French mother sauce. I believe that Careme considered it one, it may have been aioli but that has also built a different meaning than it used to. An aioli is just mayonnaise I mixed with other shit typically, I didn't start it don't come at me
  • Varine Varine:
    It's very hard to do it on a large scale though
  • Varine Varine:
    Depending on how you pour the oil the consistency can vary wildly, but that's true for most emulsions. I can only make about two quarts at a time with my robo coup, and if I have to make several in series because I forgot to order it becomes really obvious even when I do it. We have to wait and mix them all together to make sure we have the same thing.
  • Varine Varine:
    Hollandaise is also kind of like that, emulsions require a very steady hand to do exactly the same every time.
  • Varine Varine:
    Luckily I live in an age with electricity so it's way fucking faster, but when I was just a boy trying to find my place I had some hardcore chefs that made use do things like that by hand. It is WAY easier to get right by hand because you control it and can feel it, but it takes soooooo much longer. And on the scale a modern kitchen requires... I serve 400-500 guests on average per day right now, if I had 100 then we could do things way better
  • Varine Varine:
    But we can't do that. In the winter yeah, but I HAVE to get people through here right now so I can afford the staff that we CAN do that. We have about 100 days of summer, and if that summer doesn't make us what it will, then I can't operate the other most of the year with my staff. The owner is talking about closing two days a week to cut down on labor, I told him he should cut down on vacations and it did not go great. I do think I won though, I have to keep my fucking core staff and they have to be gainfully employed
  • Varine Varine:
    Sure some of them might take a second job, but I can't just cut my entire staff to unlivable hours, nor can I can cut them off all winter if I want them to come back.
  • Varine Varine:
    And also, there is no fucking way I'm pulling these hours come september. I only do this right now because I have to, the second I don't have to be the one doing it I won't be
  • Varine Varine:
    I have a 5 person core staff in the kitchen, not including me or Chef Ben
  • Varine Varine:
    Though two of those people are likely not making it this year. One of them has been replaced, the other I am kind of trying to. He's being a giant bitch, today I had to get onto him because in the three hours before I left he had taken like thirty minutes for cigarette breaks
  • Varine Varine:
    And he was also complaining to me the other day that he was out of weed so couldn't smoke any before work that day, and was confused about why I was annoyed he was telling me, his boss, that he is smoking weed everyday before work.
    +1
  • Varine Varine:
    Like yeah I can tell. I don't need to fucking know.
  • Varine Varine:
    So now he's getting scrutinized and will not be top of the list. I know I don't have the smartest people but I do expect them to have some common fucking sense
  • Varine Varine:
    I did do a rare thing for me and hire a girl last month without warning. Everyone was made at me because I started her at like 21, but she worked with me before and I was like don't care. She made 19 at her old job and I wanted her to come work with me, she is the best
    +1
  • Varine Varine:
    I'm going to get her a raise at the end of the summer. She wants to go to school again, but I want her to still work with me so.... she kind of can just tell me what the price is. I can go to 25 if she keeps up. I need to get her onto line more, that's what she wants, but I need her where she is and it's not fair that she doesn't get the little bit of raise that comes with it. She can do it no problem, I've worked with her there.
  • Varine Varine:
    It's just hard to move and train people unnecessarily right now. And also the line fucking sucks, it's not any more fun. This is turn and burn so I have the bankroll, and everyone suffers for it
  • Varine Varine:
    Eventually we'll get it balanced, we'
  • Varine Varine:
    we're starting online orders and stuff, but I also turn that off all the time because I barely keep up trying to be the best at Sysco shit
  • Varine Varine:
    I think it's gonna be a good fall and winter though. We're going to have a good staff, they will get along, they will be able to manage the workload and the complications, they know how to really cook this year, like every person on line knows their steak temps. Some of them use thermometers a lot and they don't always use them right, but they do know how to do it. Failure, especially in this field, is the only way to get better. They'll get it
  • Varine Varine:
    They won't get feel down while they do the thermometer, but we didn't have an instant read probe when I was learning. Like they did but god knows how off it is, you HAD to do it by feel. Even if the chef was fine with me bringing my own, it takes too long. Poke and know
  • The Helper The Helper:
    420 threads in the Artificial Intelligence forum :)
  • The Helper The Helper:
    Happy Monday!
    +1
  • The Helper The Helper:
    and then it was Tuesday!
    +1
  • The Helper The Helper:
    fyi I am going out of town to lake somewhere in bfe texas for the weekend will be gone Friday morning to sunday afternoon for a paranormal thing and some rest peace

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials
      Top