A simple way to view it is that every type of variable that extends a handle (or extends an extension of a handle) can and will leak. If you know how to open up the common.j file, you can view every type of variable and see for yourself that basically every variable type is an extension of handle, and so most things can leak.
Quote:
type event extends handle // a reference to an event registration
type player extends handle // a single player reference
type widget extends handle // an interactive game object with life
type boolexpr extends handle
type conditionfunc extends boolexpr //extension of extension handle
|
The types of variables that don't leak include reals, integers, booleans, and strings (strings leaks once per unique string, but unavoidable).
The way I've come to view it for better understanding is that anything you create will work like a unit, pretty much. If you create a unit and just leave it there all game, it'll stay there, taking up space in memory. You can set a variable to equal this unit, and you can use this variable in different trigger actions to change the unit, but really, the variable is only a pointer. The unit's data is held off someplace and the variable only points to that space. If you change the variable to another unit, the original unit's data will still remain where it is unchanged... taking up space. To remove the unit, we have to use the Unit - Remove Unit action (or RemoveUnit() in JASS) to clear the memory of it.
(If you have any programming background, think on the very name "handle" ... sounds like something that'd "point" to data, and not hold it, yes?)
Well... a unit was only a demonstration, imagine if it were a point instead. Every time you do use something like "Center of Region X" or "Random Point in Region X" in your trigger actions, it creates a point (location) at the desired spot... this point is then used in the actions you want it in. However... the point is not removed at default, you have to do it yourself. Imagine if that point being there were as obvious as a unit being there - it's taking up space whether you notice it or not.
The same thing applies to unit groups (groups in JASS), floating text (texttags in JASS; though, you can set a timed life on this), player groups (forces in JASS), and many other things. Once they're created, they'll take up space if they're not removed.
Those are the types of leaks where you create something, a handle, in game - where it stays and takes up space. However, if you ever take up JASS, you'll soon learn of local variables. You'll need to know that these variables, while only being references usually, take up space too if they're handle types. To solve that problem, you need to nullify the variables when you're done with it (but NOT before destroying whatever the variable was referencing to first! - unless you have some other way of destroying the thing it references to)
And, on another note, you might sometimes encounter times where you won't need to "clean-up" leaks where you otherwise would.
Consider this situation:
Three calls to display text to player groups. One displays to "All players," another to the player group "Player 1 (Red)", and another to the group of the player owning the triggering unit (assuming this was called after a unit did something). First of all, know that player groups will leak if you create one and don't remove it. So which of the above would leak, then? Convert it to JASS:

JASS:
function Trig_Player_1_Unit_Dies_Actions takes nothing returns nothing
call DisplayTextToForce( GetPlayersAll(), "TRIGSTR_007" )
call DisplayTextToForce( bj_FORCE_PLAYER[0], "TRIGSTR_008" )
call DisplayTextToForce( GetForceOfPlayer(GetOwningPlayer(GetTriggerUnit())), "TRIGSTR_009" )
endfunction
So we can see that the first method calls a force that is returned by the JASS function "GetPlayersAll()," let's look at this function in JASS:

JASS:
function GetPlayersAll takes nothing returns force
return bj_FORCE_ALL_PLAYERS
endfunction
It simply returns a variable... it doesn't create a force. So there it is, blizzard has some predefined variables, usually preceded by the "bj_" prefix. Since this player group has already been created, we don't need to remove it. In fact, if you remove this player group, further calls to "All players" won't work anymore... Unless you set the variable to equal a new player group that contains all players.
The case is the same for the second call, it uses a predefined variable that is set to be Player 1 (Red) (in the array, it's player-1, so 0 in the array to get player 1).
The last call to display text to a player, the owner of the triggering unit, is different, though. Look at the function "GetForceOfPlayer()" in JASS and you see this:

JASS:
function GetForceOfPlayer takes player whichPlayer returns force
local force f = CreateForce()
call ForceAddPlayer(f, whichPlayer)
return f
endfunction
You can see that they create a
new force, and add the player you want to it. This new force is set to a local variable (which, if I'm not mistaken, leaks since it's not nullified) and returns it for your use. Your message to the custom player group goes through, but the player group is never removed. This is a leak.
So we can do this to remove most of the leaks:
Or, if you want to skip the call to the function that creates a group altogether, you could do something like:
Using a custom script, you can directly set the temporary player group variable to equal the player in the array that you want. This saves some time, uses less function calls than the previous method; it also doesn't create a leak through the local variable not being nullified in the Blizzard function; and, another thing, you don't have to destroy the player group when you're done (it's predefined). Simple things like this can be discovered on your own in time.
You'll also want to be careful about not removing a specific handle, be it a point (location), unit, unit group, player group, or whatever... before you're done with it. And sure as hell make sure you don't change a temporary variable while it's being used.
For instance... you might be tempted to set a point variable to be the center of a region or the position of a unit, but have a wait before executing the trigger's actions. Well... the point will be created, the variable will be set to reference to it, but what happens if you use that variable again during the wait period? The variable will be set to a newly created point, and it will lose its reference to the old point. What happens to the old point, then? It's probably lost, taking up space, otherwise known as becoming a leak. What's more, your previous trigger probably failed to work properly. It might be hard to trace back to this problem happening if you're not looking for it.
One last note: If you set a variable to equal something predefined... for instance, like in the example above, "All players" (JASS: GetPlayersAll()), you will not want to Destroy or Remove ("clean-up") the actual handle's data, since it's not really a leak. (Deleting the handle data in this case will result in you not being able to use the "All players" predefined player group anymore) You
will, however, want to nullify the variable if it's a local. If, for some reason, it becomes necessary to set a variable to equal another variable that's set to a handle (point/location, whatever), then you won't want to destroy the second variable after you're done with it until you're done with the point/location itself (both variables are set to the
same point/location, therefore, destroying it from one variable will result in both variables not working).
Then there's the trivia: The most common leaks will probably be from unit groups and points, as others have probably said. Most people use those things quite often... "Pick every unit in Region X," or "Pick every unit in range of point X by 512.00" (hey, it leaks a unit group AND a point!) and so on. And... using stuff like Triggering Unit/Casting Unit in actions doesn't leak, despite returning a handle extension "unit". Why? Because it doesn't "create" the unit, the unit is already there, it's just returning the
reference ("handle") to the unit. A unit will, of course, be a leak if you never get rid of it (corpses will eventually remove themselves, but they're taking up space while they're decaying).
Yada yada, I'm sure I can go on this topic for a long time. The tutorials I've read just don't seem to explain it all that well. Maybe you'll find something useful in this rambling.
2009 addendum regarding local variables:
Figured I'd update this post since I still received reputation for it over a year after the original post date. Most of this information is off the top of my head, from my recollection of reading random posts and overhearing random conversation; feel free to correct any glaring mistakes.
Upon the original writing of this post, I wasn't too clear on the exact reason for a local variable leak (and I skipped out on updating this for the longest time when I did find out). I'll clarify on local variables now.
Every object in memory corresponds to a certain class/type, and handle variables of the proper types only point to this object in memory. The handle variable itself, then, is simply an ID to reference a specific object; a handle is an integer, specifically. Each time a new object is introduced into wc3, an ID is assigned to the object (be it a point, unit, unit group, player force, text tag, or any other handle object).
When an object is removed from memory (via the Remove_ and Destroy_ functions), the ID associated with the object in question would normally not be in use anymore. Wc3 attempts to recycle these IDs to reuse them with further objects. However, it doesn't recycle the ID immediately upon clearing the object from memory - instead, it first checks if there are any handle variables referencing the object before recycling the ID. There is an internal counter for IDs in use, I believe. Apparently this counter fails to decrement if you do not null a local variable that references a handle (emphasis on local variable). That is, a local variable is only used for the block/scope in question before it is supposedly cleared (in your typical programming language). Wc3 apparently does not handle decrementing the counter for a handle ID automatically - you have to force this by nulling the handle variable.
Global variables apparently are not much cause for concern; although, I am not too sure on the reason why. I suppose it is typical to reuse global variables and thus decrement a handle ID naturally that way - or perhaps globals simply do not stall the recycling process when an object is cleared. Regardless, it seems to be the popular opinion that global variables do not need to be nulled.
On another note, if you'll remember, I've essentially stated that a local variable "leak" occurs when a handle ID is not recycled when it should be. There are some cases in which you
don't want or need to recycle a handle ID, and thus, do not need to null a handle variable. This is the case if you have an object that is in the game permanently. Examples would be units permanently in the game, players (you don't recycle players during a game, yes?), and any other permanent things (recycled timers and so on). Probably the biggest concern for handle leaks would be in cases of massive object creation (for example, triggered spells / periodic unit creation / etc).
Restating: you don't
have to null a handle variable that points to a
permanent object. Somewhere above I believe I said you should null a handle that references the "All players" group preset by Blizzard. In actuality, you probably wouldn't have to bother, really.
To summarize: the two common types of leaks you used to hear about were object leaks and handle reference (aka local variable) leaks.
Object leak - occurs when a stand-alone wc3 object is created in memory and kept in memory past its intended use.
A simple example would be a triggered spell creating dummy units to cast spells for visual effect. If you never remove the dummy units after they're done casting, they have then lasted past their intended use - thus, they are leaks. Wc3 unit objects give us a lot of support to clear memory of them, however, so a unit leak is easy to clear and generally should be unheard of.
Reference leak (local variable leak) - occurs when a handle ID is kept in memory as "in use" past its intended use (ie, after the object it references is destroyed); thus, more and more handle IDs are set in memory in a table somewhere, taking up space for no reason in particular.
An example of this would be if you were to create an object and set the object to a local handle variable. If you do not null the local handle variable before that particular script ends, the handle ID in question would be forever "in use" and never recycled.
Finally, I'll say that, despite this post being updated in 2009, I haven't added any of the issues that I have discovered relatively recently. Just reading around for a few minutes showed some new possibilities regarding leaks that I was not fully aware of (given I have not been an active mapper for ~4 years). The possibility of groups leaking when destroyed is one thing I've seen, for example.
In any case, consider this post outdated. I imagine you'd only be reading this if you somehow came in upon a search or a link, anyway.