HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Variables are Memory Leaks?

12-17-2006, 01:54 AM#1
MrApples
From what I know, a memory leak is something created that is stored in memory(to allow faster accessing of it), and if not cleaned(told it is no longer needed), it remains in memory and thus takes up memory until the game is ended.

A variable also must be saved in memory, and if not nullified, don't they do the same thing? I am refering to globals and locals. Is there anyway to nullify variables other then the 'leaking' ones?
12-17-2006, 03:07 AM#2
Alevice
No, not in warcraft 3 at least. Only handle based variable types (and some others, let's not get into that yet) can cause a memory leak, for the space used by them do not get cleaned out automatically by the garbage collector. The garbage collector is a part of the game engine in charge of "cleaning the mess", that is, freeing the space reserved by "unused variables" (that is, a memory chunk that it is not referenced by any sort of variable).

Handles are not properly removed by the GC because the way they work. Handles variable type is actually just an "integer var" that points out to another space in memory where the actual data (eg, an unit, a region, etc) is truly stored. The GC is in charge of cleaning the handle in the same way that it cleans a variable integer, removing just the reference, not the chunk it pointed to.

Lets put an example. Let's say this is how wc3 memory management look like:

Zoom (requires log in)

You will see that at our left we can see the variables we can regularly work with and at the right the actual internal data from many objects pointed out by handles.

Let's suppose that all of the currently shown are local variables, just for practicity. Let's assume too that myhero and timeOfTheDay were created in the same function and myUnit was not removed from the game, and that the sound on the right was destroyed by using DestroySound() in another trigger. The GC makes its routine and this is how it looks now:

Zoom (requires log in)
(deleted items are highlighted on red; please ignore my accidentally highlighted array member, it was a mistake I am too lazy to fix)

As you can see, myUnit as a handle was removed, but the actual data, since it was not cleaned by calling DestroyUnit(myUnit) (or whatever the proper function name is) is still reserving space that can't be used by anything else, thus making it unaccessible space until the map ends. In contrast, since the sound was destroyed, its space gets freed.

This is the actual type of leaks mapmakers worry about. This is why you don't null integers.


Hopefully this made it a little clearer ;P

it shoudl be noted that this is not a really accurate representation on how the memory is mapped in warcraft, just a very simplified explanation on what such leaks are truly about.
Attached Images
File type: jpgbefore.jpg (31.9 KB)
File type: jpgafter.jpg (32.6 KB)
12-17-2006, 04:36 AM#3
BlinkBoy
Global Variables always leak, but you can delete its value, so only the identifyer(keyword or name of the variable) persists.

and yes if you want to delete a value of an integer that you aren't any longer using, you set its value to 0 and that's it, it will just save you 2 bytes of memory.
12-17-2006, 12:18 PM#4
MrApples
SO Strings and Integers do not need to be thought about, however all variables containing anything else should be nullified when not in use?

I see why the game didn't like it when I tried to set a integer variable to 'null' now.
12-17-2006, 12:45 PM#5
Vexorian
Strings need to be thought about.

Collapse JASS:
function getnondots takes string s returns s
 local integer i=0
 local integer L=StringLength(s)
 local string r=""
 local string ch
    loop
        exitwhen i==L
        set ch=SubString(s,i,i+1)
        if(ch!=".") then
            set r=r+ch
        endif
        set i=i+1
    endloop
 return r
endfunction


Collapse JASS:
function getnondots takes string s returns s
 local integer i=0
 local integer k=0
 local integer L=StringLength(s)
 local string r=""
 local string ch
    loop
        exitwhen i==L
        set ch=SubString(s,i,i+1)
        if(ch==".") then
            if(k!=i) then
                set r=r+SubString(s,k,i)
            endif
            set k=i+1
        endif
        set i=i+1
    endloop
 return r
endfunction

Both functions do the same thing but the second one will create less unnecessary strings.


Do you want to see a nice way to leak stuff?

Collapse JASS:
function err takes nothing returns nothing
  local integer array b

 ///...
   loop
        // .. do stuff (no exitwhen)

       call TriggerSleepAction(5.0)
   endloop
endfunction

Each time you do ExecuteFunc("err") it will leak 32KB
12-17-2006, 01:41 PM#6
Captain Griffen
Integer and real variables are the data in themselves, rather than pointers. As such, they cannot leak. Setting integers or reals to 0 does not save memory.

Strings are pointers, but the objects they point to are never cleaned up, so leaks are permament. As such, the way to avoid these leaks is to avoid creating distinct strings when not needed.

Handles are pointers. So long as a variable points to a handle index, the handle index will not be cleaned. However, there is also an oddity that locals that are still pointing at a handle don't decrement the count on the handle index count. So locals must not be left pointing at a non-permament handle when the thread ends. For permament handles, such as players, it makes no difference as the handle index will never be cleaned anyway.

All variables (except reals perhaps (?)) are 32 bits, that can be expressed as an integer.
12-17-2006, 07:33 PM#7
PipeDream
Reals too
12-17-2006, 09:55 PM#8
Ammorth
Strings allocate memory on the first run through, but if you use the same string again, it will not leak a new value. Making a trigger that generates a random string every second would cause problems, later on. A constant string that is used periodically will not be a problem at all.