| 07-25-2007, 06:27 PM | #1 |
I have a bit of code here which does not crash or lock the game, but freezes it for a minute, and ends the trigger prematurely. I checked for infinite loops/etc and I can't seem to find anything... so i'm hoping its my nub experience with JASS(this is really my second shot at full-JASS). Its the core code of a save load I'm working on. The test I used saved 3 values with a val of 6, and a max of 11, all same. JASS:function SaveCode takes integer c returns string local integer xi = 0 local integer xi2 = 0 local integer xi3 = 0 local integer a = 1 local integer a2 = udg_Code_Saves[c] local integer b = 0 local integer b2 = 0 local string result = null local string xs = null local string xs2 = null if ( a2 <= 0 ) then // No values saved for this code. Duh? set result = "nosaves" return result endif loop // Lets make it multi-demensional. set xi3 = ( a + ( 1000 * (c - 1))) set xi = udg_Save_Val[xi3] set xi2 = udg_Save_Max[xi3] set b = 1 // Find space needed. loop exitwhen xi2 < udg_SL_Powers[b] set b = ( b + 1) endloop // BooStuffer - Eats teh scraps. if ( xi2 <= ( udg_SL_Powers[b] - xi2 ) ) then if ( xs != null ) then if ( SubString( xs, 1, 1 ) == "1" ) then set xi = ( xi + xi2 ) endif set xs = SubString( xs, 2, StringLength(xs) ) else // Create opt error. xs = null. endif endif //BooStuffer set b = ( b - 1 ) loop if ( xi >= udg_SL_Powers[b] ) then set xi = ( xi - udg_SL_Powers[b] ) set xs = ( "1" + xs ) else set xs = ( "0" + xs ) endif set b = ( b - 1 ) exitwhen ( b == 0 ) endloop loop if ( ModuloInteger( StringLength(xs), 6 ) != 0 ) then set xs = ( xs + "0" ) else exitwhen true endif endloop exitwhen a == a2 set a = ( a + 1 ) endloop set xi = StringLength(xs) set a = 1 set b = 1 loop set xs2 = SubString( xs, a, (a+5)) loop if ( xs2 == SubString( udg_SL_BinSet, b, (b+5)) ) then // Start BooStuffer // If a value can be above 64, and is above 64, then extra is 1, else 0. Same goes for 32. // Yes it makes sense, stop forgetting that. if (b <= (udg_SL_Chars - udg_SL_Base)) then if ( xs != null ) then if SubString( xs, 1, 1) == "1" then set b = (b + udg_SL_Base) endif set xs = SubString( xs, 2, StringLength(xs)) if (b <= (udg_SL_Chars - udg_SL_Base2)) then if ( xs != null ) then if SubString( xs, 1, 1) == "1" then set b = (b + udg_SL_Base2) endif set xs = SubString( xs, 2, StringLength(xs)) else // Create Opt Error. xs was = null. endif endif else //Create Opt Error. xs was = null. endif endif // End BooStuffer set result = result + SubString( udg_SL_CharSet, b, b ) exitwhen true endif set b = ( b + 1 ) endloop exitwhen ( a2 == xi ) set a = ( a + 6 ) endloop return result endfunction |
| 07-25-2007, 06:50 PM | #2 |
Put a call to display different text inside each of the loops, and it will be pretty obvious which one is not exiting. As for loops which may be unending: - the first inner loop compares xi2 and udg_SL_powers[b]. I don't know what that array is, but are you sure it will match the conditions eventually? - the second inner loop ('BooStuffer') exits when b == 0, this should be b <= 0 just in case b is one-off from what you expect it to be. - same thing with the last condition on the first and second outer loop, use a >= a2 just in case. (there are lots of bugs in real software caused by looping conditions being too lazy like this) - The inner loop of the second loop will cause an infinite loop if udg_SL_BinSet doesn't contain xs2. In general, you want to make your loops easier to break out of by checking for 'that could never happen' conditions (like checking for a substring past the end of a string)on them. |
| 07-25-2007, 07:21 PM | #3 |
An infinite loop should cause a crash though right? Theres no waits in that code. |
| 07-25-2007, 08:33 PM | #4 |
An infinite loop should cause a momentary freeze at worst (rus until it hits the thread limit), as long as you aren't calling this multiple time. One thing I did notice though is that your one loop exits when a == xi but you increment a by 6 every iterations, which means it might pass xi without ever being exactly equal. Might want to change that to >=. |
| 07-25-2007, 08:55 PM | #5 |
The loop before that main loop makes the string divisible by 6. There isn't a problem with strings where they're longer then they say they are is there? I found the problem with this, it is a infinite loop, but its caused by something which shouldn't happen( a non-existant value being saved, different script), and i'm busy figuring out why that is. |
| 07-26-2007, 06:48 AM | #6 | |
Quote:
That's the type of thing you don't want to rely on. Writing a function like a house of cards, where future parts rely on many of the specifics and implementations of past parts, is asking for trouble. Changing the test to >= guarantees that the loop will exit when it should, AND when something goes wrong. Also, >= is ~exactly as expensive as ==, so there's not even a slow down to worry about in this case. |
