• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Hashtable Destroy w/ null handle id

Status
Not open for further replies.
Level 9
Joined
Apr 23, 2011
Messages
460
if i call to destroy an object (visibility modifier) within a hashtable through a loop that goes over all possible handles, will it run over the null values and still delete the correct values?

Example: Scenario: 6 player game. 3 players are in the game in slots 2 5 and 6. Player 2 leaves. The trigger will start setting multiboard values to notify others that the player left, and start deleting all hashtable values for all players (1 through 6) that are saved in the handles (values 1-6) of (Player Number of (Triggering Player)) then delete all the player values of that player from handles (Player Number of (Triggering Player)) of (values 1-6) to clean it up. The method of which the visibility modifiers are created is a player group variable is created and all players matching conditions is user and is playing are matched, then modifiers for players that exist are created.

If needed I can post my triggers for it, but I think this is a simple issue.
 
You can only destroy the same handle once, otherwise you will cause a double free, which will prevent your thread from being finished (which usually means the trigger gets broken).

For example, you can not do this one:

local group G = CreateGroup()
call DestroyGroup(G)
call DestroyGroup(G)

solution:
Load the handle inside your hashtable and check if it already was destroyed by performing a '== null' check before you destroy it.

better solution:
Fix the whole trigger mess. Go through this by logic and simply avoid that this could ever happen by just destroying the handle externally and then simply flushing the entries instead (to delete ghost references). I don't see why you'd actually need a hashtable for something that is bound to players. You can use arrays here without problems.
 
Level 9
Joined
Apr 23, 2011
Messages
460
The problem lies within visibility modifiers, I only want players to see certain regions of the map (ones with active players), so i have to create one for each player playing and every other player playing. So if 3 players are playing. Player 1 needs 3 visibility modifiers, as well as player 2 and 3. The reason why each needs one for each is because players can select any slot on the map, so i needed to use a hashtable to store the visibility modifiers through the first value of their number, and the second value of the corresponding player, to easily get the values later because variable arrays cant be in a variable array. (Doubled variable array) otherwise you're just storing the values of the variable at that array to the variable declared.

Edit: But yes, checking if the handle is null would fix the issue easily.
Edit2: How would I check if the handle is null? I can't seem to find the native in JassCraft and i'm pretty certain it's not in GUI.
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
Edit: But yes, checking if the handle is null would fix the issue easily.
Edit2: How would I check if the handle is null? I can't seem to find the native in JassCraft and i'm pretty certain it's not in GUI.

JASS:
if LoadUnitHandle(udg_Spell_Table, id, 1)==null then

endif

this for check if unit is null in hash

also this u can do with arrays just not worth coz far easier then with hashtable if u want make more disable/enable visibility modifier / player
 
The problem lies within visibility modifiers, I only want players to see certain regions of the map (ones with active players), so i have to create one for each player playing and every other player playing. So if 3 players are playing. Player 1 needs 3 visibility modifiers, as well as player 2 and 3. The reason why each needs one for each is because players can select any slot on the map, so i needed to use a hashtable to store the visibility modifiers through the first value of their number, and the second value of the corresponding player, to easily get the values later because variable arrays cant be in a variable array. (Doubled variable array) otherwise you're just storing the values of the variable at that array to the variable declared.
Simply store the 6 visibility modifiers to a player ID in a table for each player existing.
When the player leaves, simply destroy all the modifiers and flush the child table. I don't see why you should have troubles with cross references here.
You can create visibility modifiers for players not existing ... it won't cause bugs or anything else, so it doesn't really matter. Just make sure you don't destroy the same modifier twice.
In the end I wouldn't even bother to destroy them. Just turn them off if you don't need them to move during the game.
JASS:
native FogModifierStop takes fogmodifier whichFogModifier returns nothing


Edit: But yes, checking if the handle is null would fix the issue easily.
Edit2: How would I check if the handle is null? I can't seem to find the native in JassCraft and i'm pretty certain it's not in GUI.
In JASS, visibility modifiers are called FogModifiers.
JASS:
native LoadFogModifierHandle	takes hashtable table, integer parentKey, integer childKey returns fogmodifier
native SaveFogModifierHandle	takes hashtable table, integer parentKey, integer childKey, fogmodifier whichFogModifier returns boolean
You can also use native HaveSavedHandle takes hashtable table, integer parentKey, integer childKey returns boolean, which is a little bit faster than loading the value. But as you usually want to destroy them, you need to load anyway.
 
Level 9
Joined
Apr 23, 2011
Messages
460
That's kinda what i did, but i guess hiding it would mean i avoid the double destroy. Here's what occurs. btw I did it in GUI for simplicity. My reasoning for destroying them was i thought it was cause lag if I left them there, like leaks, but I guess it doesn't matter.
  • Init
  • Hashtable - Create a hashtable
  • Set hash = (Last created hashtable)
  • For each (Integer A) from 1 to 6, do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Player((Integer A))) is in Players_Group) Equal to True
        • Then - Actions
          • For each (Integer B) from 1 to 6, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Player((Integer B))) is in Players_Group) Equal to True
                • Then - Actions
                  • Visibility - Create an initially Enabled visibility modifier for (Player((Integer A))) emitting Visibility across Player_Area[(Integer B)]
                  • Hashtable - Save Handle Of(Last created visibility modifier) as (Integer A) of (Integer B) in hash
                • Else - Actions
        • Else - Actions
is how they are created. And then
  • Player Leaves
    • Events
      • Player - Player 1 (Red) leaves the game
      • Player - Player 2 (Blue) leaves the game
      • Player - Player 3 (Teal) leaves the game
      • Player - Player 4 (Purple) leaves the game
      • Player - Player 5 (Yellow) leaves the game
      • Player - Player 6 (Orange) leaves the game
    • Conditions
    • Actions
      • Set p = (Triggering player)
      • Set pnum = (Player number of p)
      • Multiboard - Set the text for Multiboard item in column 1, row (pnum + 1) to Left the Game!
      • Multiboard - Set the text for Multiboard item in column 2, row (pnum + 1) to Left the Game!
      • Unit - Remove Hero[pnum] from the game
      • For each (Integer A) from 1 to 6, do (Actions)
        • Loop - Actions
          • Visibility - Disable (Load (Integer A) of pnum in (Last created hashtable))
          • Visibility - Disable (Load pnum of (Integer A) in (Last created hashtable))
      • Custom script: set udg_p = null
disables them. Or am I missing something?

edit: fixed player leaves trigger to not declare player number function more than once.
 
Last edited:
Don't care about the fogmodifier leak in this situation. As you only create those modifiers once and don't have like thousands of them, your machine will laugh at you for trying to remove them just for performance reasons. :)

Leaks usually don't matter when they aren't used in periodic events or in hundreds of instances.

Btw in this case, you can also just destroy the fogmodifiers, as you (by logic) will never cause a double free.
Just make sure you exclude the integer A = pnum case in your second loop action as this is the only thing that will definitely cause a double free.
 
Status
Not open for further replies.
Top