• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!
  • ✅ The POLL for Hive's Texturing Contest #34 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!
  • ✅ The POLL for Hive's Techtree Contest #20 is OPEN! Vote for the TOP 3 FACTIONS! 🔗Click here to cast your vote!

How dangerous are "random number between X1 and X2" conditions?

Level 16
Joined
Jun 9, 2008
Messages
346

Shortlegs

I won't bore you retelling my tale again, the quick recap is just that in my project the MBs keep climbing, and any version of the map where the MBs reach 800 by 30min will probably reach 1GB by the first hour and then crash long before it reaches the second hour. But even in the best versions, the MBs are climbing, just more slowly (rarely shrinking).

I have been leak hunting, and I cannot figure out what could still leak. I always delete points and unit groups and regions, and that's in the cases where I don't just use constant groups and "move region" (something I try to do as much as possible).

But now I remember someone once told me that ANY function that forces the machine to "think" (say, calculate a random number, count number of units in a group, etc.) will leak.
Is that true?

If so, that could be an angle here, because my project rather heavily relies on different outcomes depending on "dice rolls" like "If random number between 1 and 10 less than or equal to..."

1) So are functions like that inherently problematic, and are there alternatives?

2) Is there a more likely explanation you could think of? I suppose my map spawns a rather large number of units (large number of players training units, AI players get extra units with triggers, creeps killed in one location respawn at another part of the map, so overall population always at least slighlty grows rather than declines over the course of a game), but it's not either like I create like 1000 units with a periodic trigger or anything like that.
 
1. No. No.
Well, there's that, at least.
2. Point leaks, Unit Group leaks, Player Group leaks, Special Effect leaks.
got all of those covered, as far as I can tell, though of course I got bigass triggers that could still hide something...

How does Warcraft 3 crash from memory usage, though? Seems unlikely unless you're on pre-1.31.
I am on 1.29, lowest possible version that still allows big maps; the version I am most familiar with.

Now, correlation is not causation, but it IS rather noticeable that the speed of the crash always seems to correlate with those mb numbers (sooner the faster it climbs).
 
Well, there's that, at least.

got all of those covered, as far as I can tell, though of course I got bigass triggers that could still hide something...


I am on 1.29, lowest possible version that still allows big maps; the version I am most familiar with.

Now, correlation is not causation, but it IS rather noticeable that the speed of the crash always seems to correlate with those mb numbers (sooner the faster it climbs).
I would upgrade to at least 1.31, it's not like it's going to be unfamiliar. Then you can enjoy a 64-bit client. (Backup maps before doing so)

Otherwise, it really is just a matter of properly cleaning up memory leaks (assuming that's the source of the crash). Nulling locals could be another one you're forgetting. Isn't there some kind of "leak detector" system you can use? I've seen some on Hive.
 
I would upgrade to at least 1.31, it's not like it's going to be unfamiliar. Then you can enjoy a 64-bit client. (Backup maps before doing so)
Okay, I'll check, though even if that prevents the crashes, I kinda like the idea of finding those leaks and solving the core issue behind this, so for now I'll keep trying!
Otherwise, it really is just a matter of properly cleaning up memory leaks (assuming that's the source of the crash). Nulling locals could be another one you're forgetting.
I always get confused with that - I exclusively use GUI (other than the custom script remove functions), and usually I will have variables like Set [SillyUnitNameUsedInEveryTrigger] = Last Created Unit. My understanding was that in those cases I don't need to null?
However, units with arrays might be a different issue
Isn't there some kind of "leak detector" system you can use? I've seen some on Hive.
I always dreamed of something like that, but last time I checked, there was only a tool said to no longer work, and the wisdom that "the only leak detector you'll ever need is yourself". Maybe this has changed in the meantime
 
I always get confused with that - I exclusively use GUI (other than the custom script remove functions), and usually I will have variables like Set [SillyUnitNameUsedInEveryTrigger] = Last Created Unit. My understanding was that in those cases I don't need to null?
However, units with arrays might be a different issue
Intuitively I also figured you wouldn't need to null variables in a case like that, but I heard some other people on the discord say that you actually do. It might be worth a try to see if that fixes your problem.
 
Okay other leak question - out of curiosity I DID run the outdated leak checker and it says the location 'Pointe' here leaks something fierce:
  • Set Pointe = ((Position of Tanker[Statstore]) offset by 200.00 towards 270.00 degrees)
  • Region - Center Attackzone <gen> on Pointe
  • Custom script: call RemoveLocation (udg_Pointe)
I have NO IDEA why that would be. I delete 'Pointe', right? shouldn't that take care of it
 
Yes, for Locations, removing is sufficient. In this case, there are two location references being created and you're only cleaning the leak for one of them. (Position of Tanker[Statstore]) should be a variable itself which is then used to generate the value of Pointe, and must also be removed.

So you should do something like:
  • Set temp_location = (Position of Tanker[Statstore])
  • Set Pointe = (temp_location offset by 200.00 towards 270.00 degrees)
  • Custom script: call RemoveLocation(udg_temp_location)
  • Region - Center Attackzone on Pointe
  • Custom script: call RemoveLocation(udg_Pointe)
 
Yes, for Locations, removing is sufficient. In this case, there are two location references being created and you're only cleaning the leak for one of them. (Position of Tanker[Statstore]) should be a variable itself which is then used to generate the value of Pointe, and must also be removed.

So you should do something like:
  • Set temp_location = (Position of Tanker[Statstore])
  • Set Pointe = (temp_location offset by 200.00 towards 270.00 degrees)
  • Custom script: call RemoveLocation(udg_temp_location)
  • Region - Center Attackzone on Pointe
  • Custom script: call RemoveLocation(udg_Pointe)
Thank you, but also groan. Guess one should never underestimate the number of layers needed
 
Thank you, but also groan. Guess one should never underestimate the number of layers needed
Whenever you see the words (Position of) know that the game is creating a Point. But what is a Point exactly? It's an object that contains X, Y, Z coordinates. Warcraft 3 exists within an XYZ grid, it's how everything is positioned in the game world, it's how the pathfinding algorithm can determine where units should go, what's blocked, what's open, etc. So Points are a way to interact with a position within that grid.

And since Points are more complex objects, unlike Integers, Reals, Booleans, and Strings, they need to be discarded when you're done with them --> call RemoveLocation(). The same is true for other more complex objects like Unit Groups, Player Groups, etc.

If you ever upgrade to writing your own code, you'll notice that 99% of the functions you used in GUI have coordinate based alternatives. This means you can bypass the need for a Point and punch in the coordinates yourself. These functions are faster, don't leak, and are generally easier to work with.

My understanding was that in those cases I don't need to null?
You only need to null non-primitive local variables.

Nulling local variables can only be done in GUI by using Custom Script:
  • Events
    • Unit - A unit Starts the effect of an ability
  • Conditions
  • Actions
    • Custom script: local unit MyCaster = GetTriggerUnit()
    • Wait 1.00 seconds
    • Custom script: call KillUnit(MyCaster)
    • Custom script: set MyCaster = null
You have to null MyCaster in this situation or it will leak. You probably aren't doing this anywhere and can rule it out as a cause of your memory leaks.

When it comes to nulling global variables, it does actually alleviate some memory usage in certain cases. However, note that this is not a memory leak issue and should really only matter in pre-1.31. Here's an example:
  • Events
    • Unit - A unit Starts the effect of an ability
  • Conditions
  • Actions
    • Set MyCaster = (Triggering unit)
    • Wait 1.00 seconds
    • Unit - Kill MyCaster
    • Custom script: set udg_MyCaster = null
That last line of Custom Script is removing the reference to the casting unit. That means it's no longer being held in memory. This does NOT solve a memory leak, because nothing is leaking here. However, it does free up a very small amount memory. If you have 1000's of variables like this then it might be beneficial to null them when they're not in use - but I find that hard to believe since they're so small in size.

Lastly, it's important to understand that a memory leak is when you've lost the ability to fix the problem. If you can still add a line of Custom Script to "Destroy/Remove" the object in question then you're not dealing with a memory leak. You're dealing with a potential memory leak, but not a memory leak.
 
Last edited:
Lastly, it's important to understand that a memory leak is when you've lost the ability to fix the problem. If you can still add a line of Custom Script to "Destroy/Remove" the object in question then you're not dealing with a memory leak. You're dealing with a potential memory leak, but not a memory leak.
That's an interesting distinction that I never learned. Thanks for offering so much extra detail! :smile:
 
Back
Top