Tool that pinpoints jass leaks?

ZakkWylde-

New Member
Reaction score
14
Can someone point me to a tool that finds leaks (as a result of coding JASS/vJass--I heard some are better for GUI...[??])?
Would this tool also be able to pinpoint the leak so that it would be easy to find its cause and fix?

Thanks,
Zakk
 

Darthfett

Aerospace/Cybersecurity Software Engineer
Reaction score
615
I don't know of any tools for JASS leaks, though there was Leak Checker for the GUI. It's probably not up-to-date, but should still work.

I would recommend reading a tutorial on leaks and manually correcting your code (and in the future just avoiding the leaks in the first place). It will teach you things you actually need to think about when programming.
 

inevit4ble

Well-Known Member
Reaction score
38
As I understand it, any handles leaks. So things like integers, reals and values as such dont but groups, units and players do.

Thats my understanding
 

tooltiperror

Super Moderator
Reaction score
231
The non-handle base types ([ljass]string[/ljass], [ljass]code[/ljass], [ljass]real[/ljass], and [ljass]integer[/ljass]) do not have to be managed at all, they are automatically handled by the engine.

Types that extend handle (you can see all of the types which do in common.j) have to be nulled if local, sometimes also destroyed, except for variables of the type [ljass]player[/ljass].

In an initialization function (thistype.create() is not initialization) you do not have to nul your locals.
 

Darthfett

Aerospace/Cybersecurity Software Engineer
Reaction score
615
I don't know if there are any tutorials specific to leaks in JASS. However, there were some incorrect/not mentioned things posted above. I'll now give you a tutorial (and yes, it's accurate).

[ljass]string[/ljass]s and [ljass]boolexpr[/ljass] (with the exception of those returned by [ljass]And[/ljass], [ljass]Or[/ljass], and [ljass]Not[/ljass]) types leak exactly once, meaning that they are reused/recycled if they have already been created. For example, a giant loop displaying every possible string combination will end up using a lot of memory, that cannot be reclaimed (until the game ends). Boolexpr, on the other hand, can be destroyed, though it's only practical if you're using tons of them, or using the And/Or/Not functions.

The only variable types that create leaks if not removed, extend [ljass]agent[/ljass], which then extends handle. There are a few additional handle types that also must be destroyed, but you should think of them as exceptions to this rule.

[ljass]handle[/ljass] Exceptions: (Possibly an incomplete list)
  • [ljass]boolexpr[/ljass] - Explained above
  • [ljass]trigger[/ljass] - Rarely destroyed in practice, and there are many bugs related to destroying a trigger (especially if the current function was run via that same trigger)
  • [ljass]image[/ljass] - Rarely used
  • [ljass]lightning[/ljass]
  • [ljass]ubersplat[/ljass] - Rarely used
  • [ljass]texttag[/ljass] - There is a maximum number of texttags on the map at any one time, and creating additional after this number will not work (not sure of the effects). They are recycled, and the memory for them is pre-allocated.


Essentially every form of removing a leak is done by using the DestroyXXXXX function corresponding to the name of the type of variable, such as [ljass]DestroyTrigger[/ljass], [ljass]DestroyTextTag[/ljass]. A few exceptions would be [ljass]RemoveUnit[/ljass] and [ljass]RemoveRect[/ljass] (I don't know any others off the top of my head).

___

There is another way you must take care of leaks, that is mostly specific to JASS. While the actual data will be destroyed by calling the various Destroy/Remove functions on the variable, the memory will still be allocated until there are no more references to the location in memory. The game keeps track of how many references with a counter. When the counter reaches 0, the memory is recycled.

With global variables in GUI, this is usually not an issue, since the variables are global and usually re-used. However, in JASS, there are local variables, which due to a bug in the engine, do not decrease the reference counter when they go out of scope (A.K.A. when the function ends). This means that you must manually de-reference the place in memory, by setting the local variable to null:

JASS:
function foo takes nothing returns nothing
    local unit bar = CreateUnit(...)
    call RemoveUnit(bar)
    set bar = null
endfunction


If you forget to do this, it is also considered a memory leak. This type of de-referencing is only needed for types that are destroyed ([ljass]player[/ljass] would be a type of handle that never needs to be nulled), so if you never destroy a trigger, any variables referencing the trigger never need to be set to null.

As is said above, the primitive types (excluding handles): [ljass]integer[/ljass], [ljass]boolean[/ljass], [ljass]real[/ljass], [ljass]string[/ljass], and [ljass]code[/ljass], do not need to be nulled, nor destroyed to have "memory-leak free" code. Keep in mind that as I said earlier, strings still do cause minor leaks, but there is no possible way to avoid them, and you shouldn't worry about them.

I hope this will give you a thorough understanding of leaks, let me know if you don't understand something, or have some questions about this. :)
 

tommerbob

Minecraft. :D
Reaction score
110
I've always nulled string and player locals. :eek:

That info was really useful. Thanks darth
 

ZakkWylde-

New Member
Reaction score
14
Thank you for the info (+rep, of course). I presume this means I need not worry about nulling globals, because they will be recycled/reassigned the next time I use them (?).

Now, a question about the BLACK SCREEN that sometimes appears at the end of any map.
From my understanding, that is basically your computer sorting out all of the jumbled up/leaked/whatever memory. The longer the screen, the more leaks the map had, correct?
After playing my map for an hour and a half (or so), the black screen was PRETTY lengthy, like 3-5 seconds. Is this because leaks have accumulated over time, or is this something that just happens as the game runs longer and longer?

From what you told me and what I understood, I don't think I have regular leaks--or at least not that many. (That is, they would only show up in the case where I forgot to null a unit, or something.)
But the long-ish black screen is giving me doubts.
Thoughts?
 

Dirac

22710180
Reaction score
147
because they will be recycled/reassigned the next time I use them (?).
No, you don't have to null them, but you do have to destroy them before you set them to something else. For most cases you don't ever have to reassign a global to another handle
JASS:
globals
location loc
endglobals

private function afterInit takes nothing returns nothing
call RemoveLocation(loc)
set loc=anoterLoc
endfunction

private function onInit takes nothing returns nothing
set loc=someLoc
call TimerStart(CreateTimer(),0,false,function afterInit)
endfunction

I have no knowledge at all about the "black screen" after the game closes. It might be related to leaks, yes
 

Darthfett

Aerospace/Cybersecurity Software Engineer
Reaction score
615
Thank you for the info (+rep, of course). I presume this means I need not worry about nulling globals, because they will be recycled/reassigned the next time I use them (?)

The nulling, as Dirac said is not needed, but if the type leaks, and you don't want it around (e.g. it's a location, not a unit which you likely want to keep around), don't forget to remove it before reassigning it.

Now, a question about the BLACK SCREEN that sometimes appears at the end of any map.
From my understanding, that is basically your computer sorting out all of the jumbled up/leaked/whatever memory. The longer the screen, the more leaks the map had, correct?
After playing my map for an hour and a half (or so), the black screen was PRETTY lengthy, like 3-5 seconds. Is this because leaks have accumulated over time, or is this something that just happens as the game runs longer and longer?

I don't know for sure, but I suspect leaks/memory is the cause. Having a large amounts of units on the map, or other objects may also contribute to this, if I'm right, in which case there's not much you can do about it.

From what you told me and what I understood, I don't think I have regular leaks--or at least not that many. (That is, they would only show up in the case where I forgot to null a unit, or something.)
But the long-ish black screen is giving me doubts.
Thoughts?

I think location leaks are the most common in GUI, JASSers tend to have issues when they forget to null a local before it goes out of scope, which usually causes problems when you have a custom spell (where there is often a high frequency periodic loop).

One way to see how the performance is doing, is to use a handle counter. That will give you an idea if there are leaks - if there is a constant increase in the total count (and it never goes back down).
 

Darthfett

Aerospace/Cybersecurity Software Engineer
Reaction score
615
Is a handle counter something I would download and run alongside WC3?

No, it's a type of system that uses a leaderboard or multiboard to display the current total number of handles (or a good estimate, it's not extremely accurate).

emjlr3 once made one, and it's an approved resource, but it wasn't very reliable, as it only created one handle (and handles' ids are recycled), so it wasn't very stable. However, I modified it to simply create 100 at a time, to get past some of those recycled handles. Here's the code:

JASS:
library HandleCounter initializer Init

globals
    private leaderboard handleBoard
endglobals

private function Callback takes nothing returns nothing
        local integer i = 1
        local integer id
        local integer idmax = 0
        local location array P
        loop
                exitwhen i > 100
                set P<i> = Location(0,0)
                set id = GetHandleId(P<i>)
                if id&gt;idmax then
                        set idmax =id
                endif
                set i = i + 1
        endloop
        loop
                set i = i - 1
                exitwhen i &lt; 1
                call RemoveLocation(P<i>)
                set P<i> = null
        endloop
        call LeaderboardSetItemValue(handleBoard,0,idmax-0x100000-100)
endfunction

private function Actions takes nothing returns nothing
        set handleBoard = CreateLeaderboard()
        call LeaderboardSetLabel(handleBoard, &quot;Handle Counter&quot;)
        call PlayerSetLeaderboard(GetLocalPlayer(),handleBoard)
        call LeaderboardDisplay(handleBoard,true)
        call LeaderboardAddItem(handleBoard,&quot;Handles&quot;,0,Player(0))
        call LeaderboardSetSizeByItemCount(handleBoard,1)
        call Callback()
        call TimerStart(GetExpiredTimer(),0.2,true,function Callback)
endfunction

//===========================================================================
function Init takes nothing returns nothing
        call TimerStart(CreateTimer(),.01,false,function Actions)
endfunction

endlibrary
</i></i></i></i>


It's a vJass library, but it wouldn't take much to make it regular JASS. It should be just copy and paste into Newgen to get it working.
 

ZakkWylde-

New Member
Reaction score
14
EDIT: removed random problems I had posted here...trying it now with problems gone.

EDIT2: So the handle count started at about 3170...I have a restart function in my game--when that was triggered, it seemed to jump about 200 (and then my comp froze...for other reasons).
This would indicate leaks, then? (the jump, that is--the 3170 isn't important, it just serves as a baseline, right?)

<3
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
It might indicate leaks. It depends. Handle counts aren't 100% accurate because of the way the handle stack works.

If you have handles:
1 - 2 - 3 - 4 - 5
And you destroy "3", this is how it looks:
1 - 2 - empty - 4 - 5
So the next time you create a handle, it won't be assigned as "6", it will be assigned as:
1 - 2 - < 3 > - 4 - 5
Instead. So when you read off the handle, it might actually show that you have 3 handles instead of 5. Sadly, there isn't really a way around it aside from hooking everything and whatnot. You can also try AgentStats (by Jesus4Lyf), although it might suffer the same dilemma.

Generally, spam the handle count read over and over and see if it is constantly increasing. If it is, you are most likely leaking. If it is just jumping between two numbers, then you probably aren't leaking. By "leaking", I mean the important leaks. (periodic leaks) The rest you should just find by reading over your code, as that is the most accurate way to find them.
 

ZakkWylde-

New Member
Reaction score
14
Right, I went through all of my periodic code and found an occasion where I was leaking a local unit >.< zzzzz
but aside from that, no, the numbers were not constantly increasing (I guess they would be if it were leaking periodically xD).

I guess i'll just rummage through my code for local units and rects and other stuff I may have forgotten to nullify
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top