| 04-01-2007, 03:24 AM | #1 |
How can the following code get blamed for a "double free" error according to war3err: JASS://Clear common global variables function ClearGlobals takes nothing returns nothing if (udg_ug!=null) then call DestroyGroup(udg_ug) endif if (udg_ug2!=null) then call DestroyGroup(udg_ug2) endif if (udg_p!=null) then call RemoveLocation(udg_p) endif if (udg_p2!=null) then call RemoveLocation(udg_p2) endif endfunction Don't locations and groups become null when they are destroyed so they shouldn't make it past the if statements? Or if they don't become null then how do I check if they are not holding data to avoid double frees? I wish I had never known it was a problem to destroy empty handles and it never bothered me. |
| 04-01-2007, 03:50 AM | #2 |
No, they don't become null. ... If you ask me, the mere fact you have to check if they were removed is pretty much a terrible thing. You should avoid dealing with already destroyed handles. The obvious solution to this is setting the variable to null after calling deconstructor. |
| 04-01-2007, 03:52 AM | #3 |
Those functions don't modify the variables. They only do stuff. The actual values of the variables remains unchanged. H2I() Works because a handle type variable is just an index to actual data. Nothing about the variables are changed. Only the data they point to. So unless you explicitly set them to null, they will remain the same. |
| 04-01-2007, 04:11 AM | #4 |
I don't get it. So I remove a location and destroy a group and it is still there, how does that free up memory? Vex the reason I have to check if they were removed is because it is a generic function to clear the temporary global variables that I use and I don't necessarily set all of them in any given trigger. I just made up this function by the way, but I guess it won't be usable. So there is no way to have a generic function like this without avoiding double frees? Apart from adding variable=null in this function and then using it exclusively for clearing any of those variables. |
| 04-01-2007, 04:14 AM | #5 |
You are not nulling the reference. Right after destroying the item, you still need to clear all refrences to it. |
| 04-01-2007, 05:02 AM | #6 | |
Quote:
A handel is a pointer. local location L That crates a variable of type location, which is a sub type of handel. set l = Location(5, 34) This creates an actual location in memory, with the data "5, 34", and sets the variable to point to that value. Your variable "l" does NOT contain the "5, 34" information, it only points to it. So, when you remove the location, you're removing the "3, 34" thats stored in memory. Your variable is not at all affected by this. Its just now pointing at a blank space. |
| 04-02-2007, 02:18 AM | #7 |
And "blank space" != null ? How does war3err detect double frees? If it can detect it then there must be a way to detect a potential double free and avoid it no? |
| 04-02-2007, 02:20 AM | #8 |
blank space doesn't equal null. When you are using == or != on handles you are not comparing the objects, you are comparing the references. This is the reason GetUnitLoc(u)==GetUnitLoc(u) returns false |
| 04-02-2007, 09:08 AM | #9 |
I understand GetUnitLoc(u) won't return the same handle twice, it makes a new one each time. But I don't see why a destroyed variable shouldn't equal null if it is a pointer that points to nothing. So what does a destroyed group or a removed location equal? Is there any way to attempt to read them if only to get the answer "unreadable"? |
| 04-02-2007, 09:19 AM | #10 | |
That's the thing. The pointer doesn't point to 'nothing'. The pointer points to the memory where the handle you just destroyed was. So it will try to access that memory, and there could be something else there now because the game used that memory for something else. Quote:
No. You should never, ever try to use a destroyed handle pointer for any comparisons or functions. Ever. Don't do it. Ever. If you programming style requires it, then you have other problems. |
| 04-02-2007, 02:50 PM | #11 |
whatever stops you from doing this: JASS://Clear common global variables function ClearGlobals takes nothing returns nothing if (udg_ug!=null) then call DestroyGroup(udg_ug) set udg_ug=null endif if (udg_ug2!=null) then call DestroyGroup(udg_ug2) set udg_ug2=null endif if (udg_p!=null) then call RemoveLocation(udg_p) set udg_p=null endif if (udg_p2!=null) then call RemoveLocation(udg_p2) set udg_p2=null endif endfunction |
| 04-02-2007, 06:19 PM | #12 | ||
Quote:
Thanks for the explanation. That makes sense. Quote:
I would only require it because of this ClearGlobals function I just created. And what you suggest Vex won't work unless I convert every other use of RemoveLocation and DestroyGroup on my map to ClearGlobals or make them followed by an =null statement. I guess this function is not worth the hassle. |
| 04-02-2007, 06:23 PM | #13 | |
Quote:
Incase you didn't know, changing the value of a global is the same as nulling it. So unless your global / that index of your global array will never be used again, you don't have to worry about nulling it, only calling destroy / remove functions on it. |
| 04-02-2007, 07:33 PM | #14 | |
Quote:
Yes, but if I want to have a function that destroys/removes all the commonly used variables I would need some way of knowing if any of them have already been destroyed to avoid double free errors. So nulling them would be good way to flag them. The only problem is that I would have to go through all the triggers in my map and make sure that the variables get nulled after being destroyed, as I said in my previous post. I guess it will be better to just use jass w/locals more to avoid double free situations. |
