Local Variables and Memory Leaks

retupmoc258

New Member
Reaction score
1
I am very curious about memory leaks. Currently I am working on a map and while I see some places where memory leaks can occur, I still can't explain why the memory used for my map grows by about 500KB per second. That's ridiculously fast when nothing is being spawned and obviously causes lags within about 60 seconds of gameplay.

So here's my questions. Local Variables, do they leak? For example, I have a function with three local variables: Location, Group, Unit.

My understanding of functions, at least as they work in other programming code, is that a local variable is whiped from memory when the function is no longer being used, regardless of type.

Now I know whenever you use a function that creates a group, that group is registered independent of the function, correct? And the local variable is simply a reference for that object. The same is true of locations and units. The object remains in play until it is removed in some fashion (death works for a unit, but a location needs to be removed and a group destroyed, correct?)

So, if I have a function that creates a group for a local variable and destroys it when it's done, do I have to se the group variable to null? Similarly, with a unit, if I get a unit from say "GetSpellAbilityUnit()", do I need to set that unit variable to null before the function leaves? The unit still exists independent of my local variable, so I wonder if that leaks by storing memory after the function quits. I similarly remove my unneeded locations when I'm done with them.

So then this comes back around to the local variable idea. If I have a location, say LocationA and I have two local variables, loc1 and loc2. Then I do the following:

set loc1 = LocationA
set loc2 = LocationA

Then those are both just references, right? There's no real memory stored for them, and when the function quits loc1 and loc2 will be nulled, but the LocationA, which exists independent of the function, will still be in memory, correct? If I call "RemoveLoc(loc1)" then I actually remove LocationA, right? I know this is how it works with a unit. If I say "KillUnit" it doesn't kill the variable, it kills the unit it was referencing. Am I still on the right track?

Now, some of my triggers are currently in GUI, and a few I know cause leaks, but they are not referenced very often (and if they were, I would know about it because it tells me if it runs while WC3 is running).

But still, for some reason my memory is growing nearly 500KB per second, and it doesn't seem to stop no matter how long the map is running.

I was also wondering if someone would mind taking a look at my map triggers to see if they could identify where the memory problem is coming from. I do use a couple hashtables, including one that uses indexes of any unit that meets the requirements and changes values. But, I can't imagine this being the cause of a continual growth since I use the index values that never change for units that are not growing in number. Is there anyone who would be willing to take a look at it?
 

Attachments

  • Zalent_EGUI.wtg
    78.5 KB · Views: 205

Bogrim

y hello thar
Reaction score
154
Local variables leak as global variables do. You still need to remove locations and destroy groups. However, you also need to null local variables after destroying the handle, performed by simply setting the variable to "null":
Trigger:
  • Actions
    • Custom script: RemoveLocation( l )
    • Custom script: set l = null

If your map grows by 500KB per second, then it's probably one of your periodic triggers that is leaking and you can narrow your search down. However, I'm not going to look your entire map through for leaks.
 

retupmoc258

New Member
Reaction score
1
Alright. Because I've thought that's the case, I have been Removing locations and setting them to null, and I have been doing the same with units, and the same with effects (which I rarely use anyway), and groups, and everything. All my main functions that are being called are doing that. What about the variable that is used for the function. For example, I use a function that takes a location. Does the location leak into the new function. Say I have:

JASS:
Func1 takes location Loc1 returns nothing
//actions
endfunction

Func2 takes nothing returns nothing
local location Loc1 = Location(something)
call Func1(Loc1)
call Remove(Loc1)
set Loc1 = null
endfunction


Will that leak the location, even though Func2, which called Func1, destroys the variable when it is done with it?

Honestly, I have been searching everywhere for the most likely leaks, and nobody can give me any good answers. I do everything, perhaps more, to fix the problem and I still can't find the memory leak.

Here's another example I question. Because I'm looking at objects, and setting a variable equal to an existing object SHOULD NOT create a new object, but I wonder.

JASS:
local timer Exp = GetExpiredTimer()
local integer this = GetTimerData(Exp)
local location NewLoc = GetUnitLoc(.Hero)

if DistanceBetweenPoints(NewLoc, .Position) >= 60.00 then    
    set .Stamina = .Stamina + LoadReal(udg_Hash_Lookup, SHStamina, SHBuildOne)
endif
if GetUnitState(.Hero, UNIT_STATE_LIFE) < .HP then
    set .Fortitude = .Fortitude + LoadReal(udg_Hash_Lookup, SHFortitude, SHBuildOne)
endif
set .AuraHP = .AuraHP + .Aura
set .HP = GetUnitState(.Hero, UNIT_STATE_LIFE) + R2I(.AuraHP)
call SetUnitState(.Hero, UNIT_STATE_LIFE, .HP)
set .AuraHP = .AuraHP - R2I(.AuraHP)
call RemoveLocation(.Position)
set .Position = NewLoc
set NewLoc = null
if not .Alive then
    call PauseTimer(Exp)
    return
endif
set Exp = null

call .SetAllStats()


So, in my method, I remove the old position that was saved and just set it as the NewLoc and then set the NewLoc to null. If I understand objects, this shouldn't cause any leaks because the object can have as many variables referencing it without generating new objects. But if warcraft is different, then this is a big problem. If it generates a new object every time you set one variable equal to another, then that's a big problem. But if it did that, then setting a unit equal to some function that gives you the unit would, in reality, generate another unit, which it doesn't. So, is this code leak free?

What about this set of commands? It shouldn't cause a leak, I wouldn't think, but I just realized that it could . . .

JASS:
if ( HeroHP >= 4096 ) then
    call UnitAddAbility( .Hero, 'A02A')
    set HeroHP = HeroHP - 4096
else
    call UnitRemoveAbility(.Hero, 'A02A')
endif


Okay, well answers to those questions are great, but I think I found it out . . . not sure why I didn't think of it sooner. I think it's the multiboard system. It is the setup, which runs each time a unit is selected. I have set it so the old multiboard is destroyed, then a new one is created. But this runs each time a unit is selected, so I'm guessing that when I select 3 units it runs each of them simultaneously as possible, causing major lags and unstable growths in memory allocation. It seems strange, though, because each time it starts it immediately is supposed to destroy what was already there. So why would this be causing so much of a memory problem? Any suggestions how I might fix this problem? I can imagine everytime a unit is selected what it does is add it to a group, then activate a timer, or "start" the timer and set it for .02 seconds or something, and so each time it is activated simultaneously, the same timer is just re-set and it will only activate the trigger if the timer actually expires. Does that seem like a good idea? The timer would be a single global timer. This isn't a permanent feature, but it's something I'd like to be able to use while I'm alpha testing my map.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top