HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Memory Leak trouble!

02-26-2004, 10:13 PM#1
Remy
Could any check out this map if you do not have WEU and this map if you do have WEU. There is a memory leak somewhere inside the map but I can't find it. I don't know that much about memory leaks so I guess it's just me. Could anybody please check where the memory leak is and solve it? The map only has a few (3) small triggers that need to be checked so it shouldn't be a lot of work.

I would greatly appreciate it, Remy.
For info about the map check the first person view link in my sig.
02-26-2004, 10:38 PM#2
Narwanza
One problem I see is you are setting a location equal to something every 1/100 of a second. That is going to leak fast. Use call RemoveLocation(udg_PreviousHeroPosition[udg_integer]) and set it to null in custom script lines. Then set it to a new position.
02-26-2004, 10:58 PM#3
Remy
Quote:
Originally posted by Narwanza
One problem I see is you are setting a location equal to something every 1/100 of a second. That is going to leak fast. Use call RemoveLocation(udg_PreviousHeroPosition[udg_integer]) and set it to null in custom script lines. Then set it to a new position.


Oke, it's still not really clear for me. Do I remove the location after I declare it? Would that not clear the variable?!
And suppose I need to put in in front of the declare action so I destroy the previously declared variable or something, would this be okay?:

Loop from 1-a million:call RemoveLocation(udg_PreviousHeroPosition[udg_integer])
Set PreviousHeroesPosition[Integer] = HeroesPosition[Integer]
Set HeroesPosition[Integer] = (HeroesPosition[Integer] offset by Real towards HeroesFacing[Integer] degrees)

Or would I need to do this?:

Loop from 1-a million:
call RemoveLocation(udg_PreviousHeroPosition[udg_integer])
Set PreviousHeroesPosition[Integer] = HeroesPosition[Integer]
call RemoveLocation(udg_PreviousHeroPosition[udg_integer])
Set HeroesPosition[Integer] = (HeroesPosition[Integer] offset by Real towards HeroesFacing[Integer] degrees)

Could someone please explain to me what exactly happens when I declare a variable through a function and when I use a function or a variable?

If I do this:
Set PreviousHeroesPosition[Integer] = HeroesPosition[Integer]
Set PreviousHeroesPosition[Integer] = HeroesPosition[Integer]
Set PreviousHeroesPosition[Integer] = HeroesPosition[Integer]

Does it create 3new variables of which only 1 is used and of which the other 2 are 'leaks'?

If I do this:
Set PreviousHeroesPosition[Integer] = HeroesPosition[Integer]

Does it create a new variable which is then 'leaked'?
02-26-2004, 11:09 PM#4
Cubasis
Ok,

For some reason i can't download the attachment, this is a problem on my end so don't worry.

However, Your problem is likely what Narwanza tried to explain.

EVERY time you create a Object like "Point" (location in jass), you have to Destroy/Remove it after you use it to safe memory.

And EVERY time you do a Point-Call (actions that are in the Point GUI Window), They indeed create a new Point Object for you.

So what you have to do, is to create a Temporary Point variable (here named TempPoint). And:

Set TempPoint too *Whatever You Want*
*Use TempPoint Here*
Custom Script: call RemoveLocation( udg_TempPoint )


So, to make clear: Variables are NOT the Points them-selves, but instead, they are a address to a location in Memory where the Point "Object" resides. And Blizzards problem is, that if you change the address of your Variable, it does not Remove the Point Object it used to point at, but instead, it stays in memory, and thus is a memory leak.

That's why you can "RemoveLocation" a variable without destroying the variable, as that action only removes the Object, not the variable/pointer.

Cubasis
02-26-2004, 11:28 PM#5
Grater
This is what I would do:
Code:
Custom Script: call RemoveLocation(udg_HeroesPosition[udg_Integer])
Set HeroesPosition[Integer] = (Position of Heroes[Integer])

By destroying the old location before assigning a new one you ensure proper clean up.
02-26-2004, 11:32 PM#6
Kolibri
Except for the last location, but that's just being pedantic. ;)

Other memory leaks to look for are:

- Unit groups (including Do X for every unit in (New unit group))
- Undestroyed Special Effects (even those you can't see anymore)
02-26-2004, 11:37 PM#7
Narwanza
That is exactly what I was suggesting Grater:ggani:. Don't forget to set locations to null before reasigning a new location though. Warcraft doesn't recycle them till they have been set to null, and RemoveLocation() doesn't do that for you.
02-26-2004, 11:55 PM#8
Kolibri
Bah, does that mean

local location tmp_loc
set tmp_loc = center of Playable Map
call RemoveLocation(tmp_loc)

will still leak?
02-27-2004, 12:13 AM#9
Remy
Quote:
Originally posted by Kolibri
Bah, does that mean

local location tmp_loc
set tmp_loc = center of Playable Map
call RemoveLocation(tmp_loc)

will still leak?

It means you can't use tmp_loc anymore after using removelocation.
It doesn't leak though. RemoveLocation should be used before the variable gains another valua or when it is not going to be used anymore.
02-27-2004, 12:15 AM#10
Kolibri
Hmm, are you sure? I have several places where I reuse a location variable without setting it to null again. That hasn't caused any bugs.

I think you are wrong. :)
02-27-2004, 12:16 AM#11
Cubasis
Narwanza:

That is not true, You do not need to set it to null, as a variable is just a pointer to a object in memory, and RemoveLocation( loc ) destroys the object no matter if something is still referencing it.

A test was made on this, and creating 100.000 Locations, destroying them every time but NOT setting them to null....leaked cirka 600 kb's .... and that is most likely related to defragmentation in WC3's memory system, as it also happens when you properly spawn and kill tons and tons of units...so it is unavoidable.

So it is only needed (and reccomended) to Destroy/Remove things like this.

Cubasis
02-27-2004, 12:30 AM#12
weaaddar
locals should be dereferenced. Bwood even suggested this.
02-27-2004, 12:33 AM#13
Kolibri
Why?

It makes no sense. And not doing so causes no issues AFAIK.
02-27-2004, 01:00 AM#14
Narwanza
There have been tests done cubasis, ones with the varible being set to null, and ones with it just destroying the location. While the ones destroying locations definitly didnt' leak as much as not, the ones where the variable was set to null leaked the least.

Quote:
It means you can't use tmp_loc anymore after using removelocation.
I will answer this with another quote
Quote:
So, to make clear: Variables are NOT the Points them-selves, but instead, they are a address to a location in Memory where the Point "Object" resides. And Blizzards problem is, that if you change the address of your Variable, it does not Remove the Point Object it used to point at, but instead, it stays in memory, and thus is a memory leak.
you can use the local temploc after it has been removed even if it hasn't been set to null.
02-27-2004, 01:10 AM#15
Grater
Take this rather poorly designed trigger to get the distance between two units:
Quote:
function distance takes unit A, unit B returns real
local location loc1
local location loc2
local real x
local real y
set loc1 = GetUnitLoc(A)
set loc2 = GetUnitLoc(B)
set x = GetLocationX(loc1) - GetLocationX(loc2)
set y = GetLocationY(loc1) - GetLocationY(loc2)
// call RemoveLocation(loc1)
// call RemoveLocation(loc2)
// set loc1 = null
// set loc2 = null
return SquareRoot(x*x+y*y)
endfunction
Have a trigger run it 5000 times a second, or something. Observe memory usage increase over a period of time.

Now uncomment the "removelocation" actions, again observe memory usage increase, it'll be a lot less.

Finally uncomment the "set loc = null" actions. Observe that the memory increase has dropped to next to nothing.

Ofcourse the best thing to do is use common.j functions whenever possible. Handle leaks are something I only care about for functions that run very, very often.