| 04-02-2004, 01:04 AM | #1 |
I'd really like a complied list of all tips and tricks pertaining to avoiding leaks/lag and other unknown things that should be standerd in jass. If we could compile the information in this thread it would be a neat guild but if theres alredy a guild out there then please tell me so I can download it! I've searched and had no luck. What I want to know is: What do I have to destory and what is the corresponding destory function? What should I be doing as a JASS scripter to avoid all possiblities of lag/mem leaks? Thanks for your help! Just to start the thread off, You should always destory triggers when they will not be called again. -be nice if someone posted the destory trig, its in another thread i think, i will look. Guild meaning a manual, a book - not - a guild of people. :: update :: Notes so far: set all local vars to null at the end of the trigger destory anything you create and set it to null at the end of the triggr destory a trigger if it will no longer be used Did I miss anything? If so what? |
| 04-02-2004, 10:19 AM | #2 |
Basicly, the most important thing when avoiding mem leaks is to: Whenever you create some kind of object (by calling a function that returns such type of object, or just create it otherwise manually). You NEED to keep track of it, and destroy it when you don't need it anymore. This is mainly for Locations and Groups. But is also for Triggers, Rects (you rarely "create" those in-game), boolexpr's, effects, timers and just most handles you create except Players and Units (you should still remove these when they have died or when you don't need them anymore). But locs/groups are much more serius than these. You destroy them by using the appropriate common native to do so. F.ex. RemoveLocation(location loc) DestroyGroup(group g) DestroyTrigger(trigger trig) .... You can look them up in common.j. But as I say, Locs/Groups are most common. A smaller leak to avoid is to always De-reference your LOCAL handle variables in the end of a function. Including Location variables, Group variables...and just any handle-type. Just do like this: set MyLocalHandleVar = null This ofcourse doesn't work if you're gonna return that variable, so you need to do other methods for that. Read this: http://www.wc3campaigns.com/showthread.php?t=52330 <-- Also notice where I mention the alternative methods to return a handle. Cubasis |
| 04-02-2004, 02:35 PM | #3 |
I didn't know locations needed deallocation. Thanks for that. Why is it so vital to dereference local variables? Aren't they deallocated when the function terminates? |
| 04-02-2004, 02:37 PM | #4 |
Nope, that's exactly the problem, for some reason, local vars aren't automatically de-referenced when they leave the scope. Cubasis |
| 04-02-2004, 07:00 PM | #5 | ||
Quote:
Quote:
To avoid leaking when you return something that leaks (be nice if someone would list the exceptions since there are so many things that DO leak if i have a list of things that DONT leak then I can figure out what does, someone said strings dont leak or something...) you create it inside the function and return that instead of returning the something Thank you for posting! |
| 04-02-2004, 10:08 PM | #6 |
Does this mean that local variables continue to occupy memory *between* function calls (i.e, they're static,) or do they actually leak memory each time the function runs? |
| 04-03-2004, 12:57 AM | #7 |
local variables are never static, they are each time re-defined, and thus, when a function finishes, they run out of scope, and can never be accessed again. The variables themselves don't really occupy memory, as ALL the variable-types (integer, real, boolean, handle, string) in WC3 are just 32-bit integers. However, depending on the type, they either store the actual value, or point at some address somewhere. wc3jass. Find and open common.j ... Only thing you need to think about...are handles, and all the handle types are defined at the start of common.j, so there is a perfect list. So basicly, everything like location, group, unit, player, you name it...is defined from "handle", so all these are handles. And you need to destroy/de-reference all/most handle-types you use. However, if you check that file out, you'll see that more than 75% of these handle types are ones that you never use, and deffinetely never create. (Remember, you only need to destroy/de-reference handles you actually create in-game). So....as I said, your main concern is Locations and Groups... And, as I warned in that other thread, is that it would only confuse you or make you draw wrong conclusions if you didn't fully understand the de-referencation problem/leak. (NOTE That the following explenation is ONLY about handle-types) To try to make it simple. Imagine it as three different things. The Variable (a 32-bit integer-address), the in-between thing (think of it just as a GIANT array containing all the handles in the game), and the true object in memory. Variable -> Handle-Array -> Object in Memory The variable stores the address of its entry in Handle Array. The Entry in the handle array both; Reference the "Real" object on it's real location in the RAM (WC3 wouldn't give us direct access to the location in ram) AND ...along most likely other things....keep track of how many "Variables" are pointing at it. Whenever we use a Destroy/Remove function, we destroy the actual "object" in memory, but the handle-array-entry remains. And it will remain untill there are no more variables pointing at it. This wouldn't be a issue if local variables automatically stopped pointing at stuff after they run out of scope...but they do. So that's exactly why we also need to always de-reference them (Set them to "null"). So...that only leaves when we want to return some handle. As we can't return a local variable AND set it too null at the same time. So, I hope the other thread makes more sense now. Cubasis |
| 04-03-2004, 02:29 PM | #8 |
Ah... I see.. So returning a local handle variable will inevitably leak memory. I have to say that irritates me greatly. I either have to use globals to return handle results or restrict myself to returning integers etc. If JASS keeps track of all references to an object anyway, why do they need to be explicitly deallocated? I can understand forcing the programmer to take responsibility for memory management in the interest of efficiency, and I can understand automatic garbage collection for the sake of ease of coding, but this is the worst of both worlds! What the hell was blizzard thinking? |
| 04-03-2004, 02:36 PM | #9 |
The reason probably is that many objects that are referenced from script do have a function in the game itself, even when you can no more reference it from the script. But they definitely should have made the stuff automatically deallocate that only has a use in script. |
| 04-03-2004, 03:46 PM | #10 |
Alfryd, That's why I pasted this thread: http://www.wc3campaigns.com/showthread.php?t=52330 - as it shows methods to allow you to return a handle without leaking the reference. Cubasis |
| 04-03-2004, 08:32 PM | #11 |
Ah, yes. I had read that earlier and felt like I'd gone through the drier and lost some loose change. Well, at least now I know I can use PolarPojectionBJ without cost. Sorry to bother. |
| 04-08-2004, 12:14 AM | #12 |
function CreateLocation_Main takes location loc returns location set loc = Location(0,0) return loc endfunction function CreateLocation takes nothing returns location return CreateLocation_Main(null) endfunction --- Ok the first function returns a location at 0,0 and the second function returns a location at null.. how does this help me in any way?? what am i missing? i followed you up to the part about how to avoid mem leaks but the above functions look crazy. "Unfortunately setting the returned value to NULL after using it doesn't seem to fix the memory leak, in other words, the only time it doesn't leak is when it returns NULL which makes it a useless fix." Thats what I came up with -- if there is no way to avoid these leaks then why do i care? if i need to pause a unit for example then i'm going to pause that unit! I want a list of functions that leak and i can fix pls... thx "So, if your wondering how to stop "memory leakes", or basicly the fragmentation of memory, just try to use as many global variables as you can, and setting strings to the maximum length that would be used, for that string. Also when you delete objects, make sure that no variables are still referencing that object. Hope that clears up any confusion on memory leakage." So should i never use local varables again? What does he mean by setting strings to the max length that they would be used? !! o_O Notes so far: set all local vars to null at the end of the trigger destory anything you create and set it to null at the end of the triggr destory a trigger if it will no longer be used Did I miss anything? If so what? |
| 04-08-2004, 02:04 PM | #13 |
I guess you got a lil confused there :) In that other thread, I took a few example-functions...These are functions that have no obvious use, as I'm not showing off the functions, i'm showing off the main "Discovery/Confirmation" discussed in that thread... So, if you understood the other parts of that thread, you would focus on the part where I define that function to "take" a location as a parameter. But the twist is, that we don't actually pass it anything, we just pass it "null", and use this "local variable" to return the handle that we want to return. We do that, becouse unlike other local variables, we don't need to "de-reference" (set to null) the variables that are defined in the function header. Thus, as we can't both return a variable, and set that variable to null, we now have a choice of using a header-variable to return the actual handle. That's what this function was trying to show. And you're also obviously reading that old thread I posted. You shouldn't, as that's making you get even more confused. The thread I Posted is ABOUT solving this problem that the old thread was discussing. Local variables are good, and no need to avoid them. Oh, and you ONLY need to de-reference local "handle" variables. Not f.ex. integer/string/real/boolean variables. Cubasis |
| 04-08-2004, 05:16 PM | #14 | |
Quote:
wc3jass: Lemme clarify for you ;) You're a bit confused. The two functions you posted are... odd. CreateLocation_Main creates a new location at the center of the map no matter what, and returns the created location. The second function simply calls CreateLocation_Main, and since CreateLocation_Main will always create a location at 0,0 and return it, and the second function just returns whatever CreateLocation_Main does, it will also always return a new location at 0,0. I don't think either of those help you at all ;) More realistically, say you are setting up a trigger based spell and you wanted to create a special effect at the location of the target. You'd do something like this: Code:
function BlahSpellActions takes nothing returns nothing
local location unitLoc = GetUnitLoc(GetSpellTarget())
//Insert code to create special effect at unitLoc here
RemoveLocation(unitLoc) //This is important
set unitLoc = null //This isn't very, don't worry about it too much
endfunction |
| 04-08-2004, 07:12 PM | #15 | |
Quote:
Could someone tell me pls where to find all the handle variables?? http://jass.sourceforge.net/doc/api/...s-handle.shtml <-- is that all them? are these the things (see link) that i want to call their remove function then set to null? Ok I understand this code Code:
function BlahSpellActions takes nothing returns nothing
local location unitLoc = GetUnitLoc(GetSpellTarget())
//Insert code to create special effect at unitLoc here
RemoveLocation(unitLoc)
set unitLoc = null
endfunction"So, if you understood the other parts of that thread, you would focus on the part where I define that function to "take" a location as a parameter. But the twist is, that we don't actually pass it anything, we just pass it "null", and use this "local variable" to return the handle that we want to return. We do that, becouse unlike other local variables, we don't need to "de-reference" (set to null) the variables that are defined in the function header. Thus, as we can't both return a variable, and set that variable to null, we now have a choice of using a header-variable to return the actual handle." help me pls.. i dont understand what you are saying!!!!!!! "we don't need to "de-reference" (set to null) the variables that are defined in the function header." meaning we dont need to null local vars? local vars opposed to global ones? what is a header-variable! isent it just a local varable? ex: local integer AmIAHeaderVar = 2 below is what i got out of your text, what am i missing?? function mrloc takes location loc returns nothing set loc = (2,0) return loc //i cant put remove/null code here bc the funct stopes once i return something right? endfunction function talktomrloc takes nothing returns nothing local location = (null) call (mrloc) endfunction "So, how can this be useful for you? Well, we know by now that we can avoid leaking references to a location while returning by just creating them on the spot (return Location(x,y)). And with groups we can ofcourse just edit a passed group. But this is a different method, and requires you just to define your return-variable in the header, and pass it "null" (or in reality whatever). This ofcourse can be considered a kind of sloppy fix, but it works, and is personally kinda simple. This can ofcourse also be implemented into a dummy function that just references the real function, as demonstrated " how!!!!!! the functions in that thread are just creating locations on return or setting a local loc to null or 0,0 -- how do i avoid the leaks? what is the code practice?... pls explain me :( |
