Mike Torrettinni 198 Posted November 4, 2022 (edited) I was sure I got rid of all Goto usage in my code. But I found this example today : for i := 0 to Length(vArray) - 1 do begin if vArray[i].SkipThisLine then goto labelSkipThisLine; ... ... labelSkipThisLine: // no code, do nothing with this data line end; This is probably close to 20 years old code, and never failed! I almost want to leave it there, just as a reminder it took me almost 20 years to get past the beginner level 🙂 Edited November 4, 2022 by Mike Torrettinni 2 Share this post Link to post
dummzeuch 1506 Posted November 4, 2022 I actually used a goto for debugging today. The reason was that at the end of a function I check the result and for a particular result I want to repeat the code in the function in order to step through it: function whatever: SomeType; label RepeatMe; begin RepeatMe: // some code that generates the result if Result = ResultIWantToDebug then goto RepeatMe; // <== put a breakpoint here // some more code end; 3 Share this post Link to post
Brian Evans 108 Posted November 4, 2022 If the code still makes sense to you years latter and you can follow it without difficulty then there should be no complaints. Applying a rule or guideline too rigidly before the skill or knowledge to do so has been acquired often makes things worse. In your example learning how to use continue; or break; to control the flow of a for loop would be best but applying a no goto rule and using multiple cascading IF's around a large blocks of code could be worse than just using a goto. The top hall of shame code I have ever seen was due to developers rigidly applying rules before the skill and knowledge to do so was acquired. It made the code more complex and a lot harder to follow to the point is was often easier to just re-write it from scratch. 4 Share this post Link to post
Mike Torrettinni 198 Posted November 4, 2022 (edited) 29 minutes ago, dummzeuch said: The reason was that at the end of a function I check the result and for a particular result I want to repeat the code in the function in order to step through it That's pretty cool idea, avoiding exiting and running project again. Edited November 4, 2022 by Mike Torrettinni Share this post Link to post
Mike Torrettinni 198 Posted November 4, 2022 1 hour ago, Brian Evans said: developers rigidly applying rules before the skill and knowledge to do so was acquire Yes, I'm definitely guilty of this. Share this post Link to post
Remy Lebeau 1403 Posted November 4, 2022 (edited) 4 hours ago, dummzeuch said: I actually used a goto for debugging today. The reason was that at the end of a function I check the result and for a particular result I want to repeat the code in the function in order to step through it I would have just wrapped the logic in a loop instead: function whatever: SomeType; begin repeat // some code that generates the result until Result <> ResultIWantToDebug; end; Or, renamed the original function and introduced a new function with the original name to call the new function in a loop: function actual_whatever: SomeType; begin // some code that generates the result end; function whatever: SomeType; begin repeat // some code that generates the result until Result <> ResultIWantToDebug; end; Edited November 4, 2022 by Remy Lebeau Share this post Link to post
dummzeuch 1506 Posted November 5, 2022 (edited) No, a loop wouldn't have worked there. It's a function that is called multiple (many) times from several places, one of these calls (I didn't even know which one) was creating the result I was interested in. A wrapper function world also have worked, something like: function whatever: SomeType; /// this is the original function function innerwhatever: SomeType; begin // some code that generates the result end; // the wrapper function calls it begin Result := innerwhatever; if Result = ResultIWantToDebug then Result := innerwhatever; // <== put a breakpoint here end; I probably should have mentioned that the function has parameters which I omitted in the example because it didn't matter. Edited November 5, 2022 by dummzeuch Share this post Link to post
Fr0sT.Brutal 900 Posted November 7, 2022 On 11/4/2022 at 9:08 PM, dummzeuch said: I actually used a goto for debugging today. The reason was that at the end of a function I check the result and for a particular result I want to repeat the code in the function in order to step through it: Interesting application; however, I'd set a breakpoint on a line after condition (the line itself could be totally useless, like "gettickcount;" or similar) and use great IDE feature "Set next statement" feature Share this post Link to post
dummzeuch 1506 Posted November 7, 2022 1 hour ago, Fr0sT.Brutal said: Interesting application; however, I'd set a breakpoint on a line after condition (the line itself could be totally useless, like "gettickcount;" or similar) and use great IDE feature "Set next statement" feature I usually do the same, with an asm nop end; on that line. Unfortunately that Set next statement feature doesn't always work as expected. Sometimes the stack gets corrupted (at least that's what I think what happens). That's why I had to resort to a different approach here. Also, that feature was introduced with Delphi 2007 (or was it 2006?) so for earlier versions you had to change the Program Counter in the CPU window (Yeah, I know, nobody cares any more about these ancient versions. I'm the only freak who still sometimes uses them.). Share this post Link to post
Fr0sT.Brutal 900 Posted November 7, 2022 46 minutes ago, dummzeuch said: Yeah, I know, nobody cares any more about these ancient versions. I'm the only freak who still sometimes uses them You underestimate how ancient Delphi legacy is 🙂 I have 2 alive projects written in D7 1 Share this post Link to post
Ian Branch 128 Posted November 7, 2022 GoTo - Another case of the right tool for the right job... 😉 Share this post Link to post
Mike Torrettinni 198 Posted November 8, 2022 Another one from the way back: this was a long function (500+ loc) and to skip all the unnecessary code and exit on first possible condition, I used ToExit label function Process: boolean; var vList: TStringList; label ToExit; begin Result := false; vList := TStringList.Create; ... // for fast execution, exit asap when condition is right if condition_to_exit then begin Result := True; goto ToExit; end; ... ToExit: FreeAndNil(vList); end; So many mistakes here, but It's been working 15+ years. Ready for a makeover! Share this post Link to post
David Heffernan 2347 Posted November 8, 2022 7 hours ago, Mike Torrettinni said: Another one from the way back: this was a long function (500+ loc) and to skip all the unnecessary code and exit on first possible condition, I used ToExit label function Process: boolean; var vList: TStringList; label ToExit; begin Result := false; vList := TStringList.Create; ... // for fast execution, exit asap when condition is right if condition_to_exit then begin Result := True; goto ToExit; end; ... ToExit: FreeAndNil(vList); end; So many mistakes here, but It's been working 15+ years. Ready for a makeover! I guess you know to use try/finally for this 1 Share this post Link to post
Mike Torrettinni 198 Posted November 8, 2022 57 minutes ago, David Heffernan said: I guess you know to use try/finally for this Yes, I do today, that code is part of my 'learn to code just enough to sell' time, so the focus was not on learning to how to do things right. Share this post Link to post
Fr0sT.Brutal 900 Posted November 9, 2022 (edited) In most cases try-finally is OK but for time-critical functions try block in Delphi is damn slow. That's where goto's remain the only option. Or, if possible, inlined sub-functions could help Edited November 9, 2022 by Fr0sT.Brutal Share this post Link to post
Lajos Juhász 293 Posted November 9, 2022 40 minutes ago, Fr0sT.Brutal said: In most cases try-finally is OK but for time-critical functions try block in Delphi is damn slow. That's where goto's remain the only option. Or, if possible, inlined sub-functions could help It's fine until you get an exception, which will result in a memory leak. Share this post Link to post
David Heffernan 2347 Posted November 9, 2022 3 hours ago, Fr0sT.Brutal said: In most cases try-finally is OK but for time-critical functions try block in Delphi is damn slow. That's where goto's remain the only option. Or, if possible, inlined sub-functions could help Really? Which architecture are you talking about? Share this post Link to post
Fr0sT.Brutal 900 Posted November 9, 2022 6 hours ago, Lajos Juhász said: It's fine until you get an exception, which will result in a memory leak. Such critical stuff by definition doesn't deal with memory allocations. 3 hours ago, David Heffernan said: Really? Which architecture are you talking about? My benchmark shows 97% slowdown on x32 and 86% on x64. However the delays become noticeable after 1.5-2M iterations. Share this post Link to post
David Heffernan 2347 Posted November 9, 2022 44 minutes ago, Fr0sT.Brutal said: Such critical stuff by definition doesn't deal with memory allocations. My benchmark shows 97% slowdown on x32 and 86% on x64. However the delays become noticeable after 1.5-2M iterations. Presumably it all depends on what is inside the try. Share this post Link to post
Stefan Glienke 2009 Posted November 9, 2022 If you are using XE2 as in your profile you could be affected by this: https://quality.embarcadero.com/browse/RSP-27375 And as David mentions depending on what is inside the try the compiler easily throws any register usage overboard and operates via stack. 2 Share this post Link to post
Fr0sT.Brutal 900 Posted November 10, 2022 David, Stefan, I was testing with simple assignment of integer loop variable to another integer. Glad to see "try" has been fixed in 10.4 Share this post Link to post
Heremik 0 Posted November 13, 2022 I use "break" unstead of "goto" in a loop. With an additionnal boolean to manage double loop. And I use try finaly to be sure to liberate memory that I have reserved. Of course, Try finaly must not be used in time critical procedure. Share this post Link to post
David Heffernan 2347 Posted November 14, 2022 On 11/13/2022 at 2:49 AM, Heremik said: Of course, Try finaly must not be used in time critical procedure. Evidence? Share this post Link to post
Rick_Delphi 14 Posted November 19, 2022 Hey, you could do this: gotoMyFunction or gotoMyProcedure or gotoGetter or gotoSetter. Share this post Link to post
Marco V 3 Posted February 27, 2023 I have a handful of gotos in my code. Mostly they have this form if compare1 then begin if compare2 then ... else goto label1 end else .... label1: IOW jumping out of a multilevel IF block is faster than just letting it run its course. It is still active code, but I haven't revalidated the decision in ages (XE 1 or 3 times or so). Which is a problem with all low-level optimizations. The code searches for aggregates in an image (blob) so is quite RDS. Share this post Link to post