• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!

Leak... Again...

Status
Not open for further replies.
Level 33
Joined
Mar 27, 2008
Messages
8,035
Does this leak ?
  • Set TempLoc = (Random point in (Playable map area))
  • Set TempLoc = (Random point in (Playable map area))
  • Set TempLoc = (Random point in (Playable map area))
  • Set TempLoc = (Random point in (Playable map area))
  • Set TempLoc = (Random point in (Playable map area))
  • Custom script: call RemoveLocation(udg_TempLoc)
From what I understand, a "leak" occurs that you never remove (null) it causing the variable to always has a pointer/value whereas it should be cleaned (does not use anymore)

From trigger above, I am overwriting the variable over and over again, and lastly, I removed it, so from my point of view, that trigger does not contain any leak because last value of TempLoc has been cleaned.

As for 4 other action above, they have been overwritten meaning that they don't carry value any longer.

Therefore, I want a clear statement from you guys (please, if you have low knowledge of "leak", don't bother reply, it may confuses others - with respect).

Does trigger above leak ?

If it does, well I know I have to do this;
  • Set TempLoc = (Random point in (Playable map area))
  • Custom script: call RemoveLocation(udg_TempLoc)
  • Set TempLoc = (Random point in (Playable map area))
  • Custom script: call RemoveLocation(udg_TempLoc)
  • Set TempLoc = (Random point in (Playable map area))
  • Custom script: call RemoveLocation(udg_TempLoc)
  • Set TempLoc = (Random point in (Playable map area))
  • Custom script: call RemoveLocation(udg_TempLoc)
  • Set TempLoc = (Random point in (Playable map area))
  • Custom script: call RemoveLocation(udg_TempLoc)
 
Yes, the first trigger leaks. You have to remember that variables are pointers, not the actual data. So when you reassign the variable, you are not replacing the data, you are just making the variable point to something else.

So... In your case:
  • Set TempLoc = (Random point in (Playable map area))
  • Set TempLoc = (Random point in (Playable map area))
  • Set TempLoc = (Random point in (Playable map area))
  • Set TempLoc = (Random point in (Playable map area))
  • Set TempLoc = (Random point in (Playable map area))
  • Custom script: call RemoveLocation(udg_TempLoc)
Line 1 creates a location, which we'll call Object A, and assigns the variable TempLoc to point to it.
Line 2 creates a location (a new one, not the same random point as object A), which we'll call Object B, and assigns the variable TempLoc to point to it.

So the question is, what happens to Object A? Nothing. You lose reference to it. That object is still floating around in memory. So how do you remove it? At this point, you can't. You don't have any variables that point to it, aka you don't have reference to it, so it is just floating data. That is the "leak" part of it.

TempLoc merely points to Object B now. Again, once it hits line 3 and creates a new object, it will no longer point to Object B so that will be lost in memory as well.

Hopefully that clears things up. So yes, you would have to use the second trigger.
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
So basically, it creates something called "Handle", am I right ?
Like SFX, Locations, Units ?

This "Handle" creation what makes the data leaks (floating around the game memory) ?

But it's different when compared to Reals, Integer, etc, right ?

So if I just TempReal 5 times, it will still point to 5th TempReal value without leaking 4 previous TempReal creation, right ?

Thanks for clarifying it ;p
 
Yep. It creates a handle in memory. Integers, reals, booleans, and code are different because it is not storing anything in memory when they are accessed. For example, if you set x = 1.54, 1.54 won't be some "object" created in memory. Yes, technically memory will be used to assign the variable but once you change the value of x, 1.54 can be disregarded. That is probably why the concept of leaks is difficult, because that is how we think the objects would behave. Strings are stored in the war3map.wts (string table), so technically they use up memory when you are done using them. But that is a special behavior that we can't really fix.

But for handles (aka: types that are not integers, reals, booleans, code, or strings) it will create an object in memory which will stay in memory until removed.

Anyway, here is a diagram I made to make things a bit clearer. In each line 1-3, TempLoc is being assigned a new location. In line 4, TempLoc is removed:
dg0115.jpg
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
So what if I set a variable which set to a same point over and over again ?
  • Set loc = (Center of (Playable map area))
  • Set loc = (Center of (Playable map area))
  • Set loc = (Center of (Playable map area))
  • call RemoveLocation(udg_loc)
Does 1st and 2nd set of variable, leaks ?
 
Well, that isn't actually setting it to the same point over and over again.
JASS:
function GetRectCenter takes rect whichRect returns location
    return Location(GetRectCenterX(whichRect), GetRectCenterY(whichRect))
endfunction

That is the function it is actually calling. It returns a new location handle each time. So in that case, the 1st and 2nd objects do in fact leak.

However, this will not leak:
  • Set loc = (Center of (Playable map area))
  • Set TempLoc = loc
  • call RemoveLocation(udg_TempLoc)
Because when you are assigning the variable, you are referring to the same object. loc gets assigned to Object A, and then TempLoc gets assigned to Object A (because loc points to Object A). Therefore, when you remove the location, you are removing Object A, so nothing is leaking. There is no Object B or anything.

However, in your example, there are 3 objects being made. Object A, Object B, and Object C. Only Object C is getting removed.

JASS is a bit weird in that way. A lot of "what leaks and what doesn't" can be found just by looking at the JASS functions. Things aren't always logical. For example:
JASS:
if GetRectCenter(bj_mapInitialPlayableArea) == GetRectCenter(bj_mapInitialPlayableArea) then
Will return false. It is not comparing what we think it would, it is checking if they are the same handles. (or if they have the same handle ID) They are two separate objects being made, therefore they are not the same thing. Although, that may be a bit confusing to understand, so don't worry about it too much.
 
Level 8
Joined
Oct 26, 2008
Messages
387
In my mind i see a huge chess board with its little black/white squares, and i think of it as the memory. When a variable is set to something, it takes 1 square to fill it with that something. Now, if the same variable is set to something else, it takes the next square to fill it up. But the first square isn't emptied, it still has that value which was former appointed to it.

But now, as purge said, is you set 2 variables in the same value, when you call the destroy function, the destroy function acts like a "cleaner" that accesses all squares and clears the ones which have the value you want cleaned. Therefore it clears both squares in the memory which have that same value, even though it was appointed to them by 2 different variables.

I hope i made some sense :ogre_icwydt:
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
defskull, look in the Hashtable GUI functions, you'll se "Save Location Handle" "Save Unit Handle" "Save Lightning Handle", etc... All the things that GUI Hashtable says can be saved has a "Handle" could turn into a leak, if not "handled" correctly

Btw, i FREAKING LOVED THIS
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
In my mind i see a huge chess board with its little black/white squares, and i think of it as the memory. When a variable is set to something, it takes 1 square to fill it with that something. Now, if the same variable is set to something else, it takes the next square to fill it up. But the first square isn't emptied, it still has that value which was former appointed to it.

But now, as purge said, is you set 2 variables in the same value, when you call the destroy function, the destroy function acts like a "cleaner" that accesses all squares and clears the ones which have the value you want cleaned. Therefore it clears both squares in the memory which have that same value, even though it was appointed to them by 2 different variables.

I hope i made some sense :ogre_icwydt:

If I understand correctly what you ment,
Not 100% correct, the only error here is:
JASS:
local location l1 = Location(0.,0.)
local location l2 = l1
doesnt mean those are two different objects or they are different cells of memory(they are but those are deallocated when systems hits endfunction if they are not global) but when you call RemoveLocation(l1) it will call RemoveLocation(l2) as well
you can imagine any handle variable being as
JASS:
local location l = Location(…)  is  local integer l = handle of new object, type location
all handle variables are pointers, when you set location l1 to location l2, the thing you actually do is say the system that the handle id of object which is under l1 should be copyied to l2
Also one variable only points to one object at time, so if i set l to loc(0.,0.) and afterwards to loc(0.,1.) and call removeloc(loc) it would only remove the mosr recent location from memory
anyways why do I write it when purge already wrote something similar with examples already? :D
 
Status
Not open for further replies.
Top