• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Trigger] Array variable delete

Status
Not open for further replies.
Level 22
Joined
Dec 31, 2006
Messages
2,216
  • call RemoveLocation(udg_TempPoint[GetConvertedPlayerId(GetEnumPlayer())])
that's the array for player number of picked player I believe.
I'm pretty sure that leaks.
The value returned by GetEnumPlayer() should be stored in a variable and then be nulled when you're finished.
Like:
JASS:
local player p = GetEnumPlayer()
call RemoveLocation(udg_TempPoint[GetPlayerId(p)])
set p = null
NOTE: GetPlayerId() returns 0-11 while GetConvertedPlayerId() returns 1-12.
 
Level 22
Joined
Dec 31, 2006
Messages
2,216
That is only when you use globals.
Locals take up memory just like globals, but they can be used only within the function they are created in and only once. When the function finishes you can't do anything more with them, so you must null them to prevent memory leaks. There is a reason for why most JASSers null locals.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Players can actually be removed... but atmost 16 leaks is hardly a concern.
I still null them just because I feel like it. However I really should start not doing so.

Global arrays do not leak and cannot be destroyed. You can always free up all the handles contained within and they will always use atmost 32KB depending on the code used. Objects within however are capable of leaking if you overwrite them before the object is terminated.

Local arrays are subject to the same leakage issue as locals are, basically they leak handlepointers to handles which the game's handle index system uses (to prevent multiple allocation of same address) so handle indexes become lost and unusable. Although handle index leaks are dozens of times better than object leaks (as they are just an address and not a whole object), they still can cause slowdowns, excessive memory usage and bug some index systems.
 
Level 22
Joined
Dec 31, 2006
Messages
2,216
There is a function called RemovePlayer(), so players can be removed.
And as DSG said, it takes up memory, maybe not so much, but after some time it will begin to lag or at least your fps will go down. I experienced that when I created my Knockback System. When I tested it for the first time it didn't take long before my fps got reduced from 70 to 50. So then I went through the whole code to find the leak and after 1 hour of searching I found the problem. I forgot to null a local player variable in a function that runs each 0.03 second, one single variable. So locals must be nulled whether you like it or not. If I could just ignore it I would have done so long ago.
 
Level 11
Joined
Feb 22, 2006
Messages
752
And as DSG said, it takes up memory, maybe not so much, but after some time it will begin to lag or at least your fps will go down.

What part of handle variables only leak if the handle they point to doesn't exist didn't you understand? If the handle still exists, the pointer, local, global, w/e, doesn't leak ANY memory, not even the 4 bytes the memory address pointer takes up.

So then I went through the whole code to find the leak and after 1 hour of searching I found the problem. I forgot to null a local player variable in a function that runs each 0.03 second, one single variable.

Obviously nulling a player pointer wasn't your problem because players are never removed unless done so by the user (which shouldn't happen) or when they are victorious or defeated (i.e. when the game ends). And local handle pointers don't need to be deallocated if the handle they're pointing to still exists. And in the case of players, they should always exist while the game is still running.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
Players can actually be removed... but atmost 16 leaks is hardly a concern.
I still null them just because I feel like it. However I really should start not doing so.

AFAIK RemovePlayer doesn't even remove the player object. It disconnects a human from the game.

And as DSG said, it takes up memory, maybe not so much, but after some time it will begin to lag or at least your fps will go down.
It does not. If you're lagging you must have screwed up something else.

not even the 4 bytes the memory address pointer takes up.
These never leak. Not even when you don't null it.

It seems like you don't really understand what a handle is.

This is how handles work:
JASS:
struct HandleReference
    integer references
    pointer theunitvar
endstruct

A handle reference contains a reference count, as well as a pointer to the handle var (in this case a unit variable).

Internally, warcraft 3 has a handle table, which basically is a large array of HandleReferences.
H2I(handle) basically returns the array index to the correct HandleReference struct.

- Whenever a handle in warcraft 3 is assigned, warcraft 3 does an array lookup and finds the correct HandleReference. Upon asigning, the reference counter is increased. The reference counter of the previous value of the handle is decreased.
- Whenever a handle in warcraft 3 goes out of scope (i.e. a function returns, thus all local variables go out of scope and no longer exist), this reference counter should decrease.
- Whenever a reference counter reaches zero, the object can be deallocated, and the HandleReference (and its array index) can now be used by another handle. As long as it's not zero, it cannot be reused because it is considered to be used already.

One problem though: blizzard screwed up on 2 areas:
1) they never implemented the part where objects are automatically deallocated when the counter reaches zero.
2) When a function returns, the handlecounters of all local variables are NOT decreased. It's a bug.

To fix bug 1, you need to manually use destructors like RemoveLocation() whenever an object is no longer needed
To fix bug 2, you need to null local handles. Since nulling basically reassigns the handle to null, it automatically decreases the reference counter of the previous HandleReference it was indexing.

You never need to remove players. Even if you do, it won't really *remove* the player completely.
You can never possibly create a new player. So it doesn't matter if the reference counter is broken or not.
Conclusion: you do not need to null players.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
It leaks atmost 64 - 96 bits, in total as a once off constant ammount if you forget to null the pointer to a handle and it leaks the handle index (type independant).

Like I said there are only 16 players or something, so the ammount potentially leaked is near unnoticable and infact makes no difference at all compaired to a single location leak as players are generally never destroyed. Each non nulled local handle basially leaks a counter, by this I mean the handle use check counter is added one higher than it should be so if the object is destroyed, the handle index will be unremovable and reusable so it equivently leaks. This leak is generally unnoticable as it is only 6-9 bytes, but it can cause systems to bug and generally lower performance of the map. Players, as they are static / constant do not really suffer from this problem and infact probably can not have their ID recycled so it causes to performance problems at all.

The worst thing that could happen is WC3 messes up when you have not nulled a local player 4294967296 as that should be the maximum capacity the reference counter. However knowing computers nowdays it will probably loop around to 0 and so be no problem at all.
 
Level 22
Joined
Dec 31, 2006
Messages
2,216
Eleandor, I know what a handle is... A handle is just another name for pointer. And units, destructables, items etc. Are just different kinds of pointers. Just like in c++.
In c++ a pointer is declared like this: someType* someName;
I.e if I have a class called "unit" I would do something like this: unit* someDood = new unit;
In Warcraft it's much simpler.

aznricepuff said:
Obviously nulling a player pointer wasn't your problem
It was. After I nulled that variable my fps stood on 70 all the time even after thousands of knockbacks. So it fixed the problem.

Eleandor said:
And as DSG said, it takes up memory, maybe not so much, but after some time it will begin to lag or at least your fps will go down.
It does not. If you're lagging you must have screwed up something else.
Nope.
Try this code and run it. If your fps isn't reduced or your not experiencing lag after some time, I'll surrender.

JASS:
scope test initializer Init
globals
    timer t = CreateTimer()
endglobals

function lulz takes nothing returns nothing
    local timer ti = GetExpiredTimer()
    local timer ti2 = GetExpiredTimer()
    local timer ti3 = GetExpiredTimer()
    local timer ti4 = GetExpiredTimer()
    local timer ti5 = GetExpiredTimer()
    local timer ti6 = GetExpiredTimer()
    local timer ti7 = GetExpiredTimer()
    local timer ti8 = GetExpiredTimer()
    local timer ti9 = GetExpiredTimer()
    local timer ti10 = GetExpiredTimer()
    local timer ti11 = GetExpiredTimer()
    local timer ti12 = GetExpiredTimer()
    local timer ti13 = GetExpiredTimer()
    local timer ti14 = GetExpiredTimer()
endfunction

function Init takes nothing returns nothing
    call TimerStart(t, 0.01, true, function lulz)
endfunction
endscope
According to you this shouldn't reduce fps. It reduced my fps by 4 after 20 min.

And even if it's almost unnoticeable, it can make systems fuck up. That little player variable made my knockback system lag.
And I've had issues with non-nulled locals before in other spells and systems.
Plus, the handle it's pointing to might get removed, handles aren't permanent.
 
Level 22
Joined
Dec 31, 2006
Messages
2,216
Dr Super Good, I didn't notice anything before 20 minutes. But it might be that my computer is getting old. I will still need to null locals, because I almost always destroy my handles.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
Eleandor, I know what a handle is... A handle is just another name for pointer. And units, destructables, items etc. Are just different kinds of pointers. Just like in c++.
In c++ a pointer is declared like this: someType* someName;
I.e if I have a class called "unit" I would do something like this: unit* someDood = new unit;
In Warcraft it's much simpler.

It seems you didn't read my post. Handles aren't pointers. They are an index to an array of structs that in turn contain the real pointer.
Why do you start babbling about c++? Pointers and handles are a different thing.

Try this code and run it. If your fps isn't reduced or your not experiencing lag after some time, I'll surrender.
Your *test code* does not contain player variables. Hence even if your claims are true, your testcode does not represent your problem.

And I've had issues with non-nulled locals before in other spells and systems.
You really didn't read my post, did you? Non-nulled locals indeed cause bugs because of what I said. But this bug is irrelevant for player variables.
 
Level 22
Joined
Dec 31, 2006
Messages
2,216
It seems you didn't read my post. Handles aren't pointers. They are an index to an array of structs that in turn contain the real pointer.
Why do you start babbling about c++? Pointers and handles are a different thing.


Your *test code* does not contain player variables. Hence even if your claims are true, your testcode does not represent your problem.


You really didn't read my post, did you? Non-nulled locals indeed cause bugs because of what I said. But this bug is irrelevant for player variables.

1. Handles are a kind of pointers, but as I said, in Warcraft it's simpler.
When you use H2I you get the address to something.

2. It wasn't supposed to contain player variables either. It was supposed to show how non-nulling of locals can cause fps reduction..

3. I didn't say those locals I had issues with was player variables.

Can a moderator please close this thread? I'm very sure Bu113t's problem is solved.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
1. Handles are a kind of pointers, but as I said, in Warcraft it's simpler.
In warcraft it's more complex than just pointers, as I've explained.

2. It wasn't supposed to contain player variables either. It was supposed to show how non-nulling of locals can cause fps reduction..
It doesn't, it only causes the reference counter bug.

3. I didn't say those locals I had issues with was player variables.
When I tested it for the first time it didn't take long before my fps got reduced from 70 to 50. So then I went through the whole code to find the leak and after 1 hour of searching I found the problem. I forgot to null a local player variable in a function that runs each 0.03 second, one single variable
I see... Not only did you say your lag was caused by not nulling a player variable, but it's also not even the cause of the lag.
Your testcode was a response to me saying un-nulled players are not the cause, so the testcode is irrelevant to your claim that players need to be nulled.
 
Level 22
Joined
Dec 31, 2006
Messages
2,216
I see... Not only did you say your lag was caused by not nulling a player variable, but it's also not even the cause of the lag.
Your testcode was a response to me saying un-nulled players are not the cause, so the testcode is irrelevant to your claim that players need to be nulled.
That issue is not the one I'm talking about.
 
Status
Not open for further replies.
Top