Skip to main content
GameDev.net gamedev.net
🔒 Locked

To goto or not to goto?

Started by Dragonion Aug 6, 2011 at 9:04 PM 92 replies 24.5k views
Original Post
Dragonion
Dragonion
Well, the title says it all I guess :)
zacaj
zacaj
I find them useful to do cleanup in functions that can fail, so I dont have to free all the resources everywhere, I can just goto the end, and put all the frees there
ArthY303
ArthY303
I never use goto statements. It's generally unsafe to change the flow of an application in this way. Almost in every situation there are more suitable techniques that are safer, and which won't create spaghetti.
patrrr
patrrr
I think you need to define the context of this question; in some languages you would be highly restricted if there weren't any "goto"s. Making some assumptions, I think Dijkstra's opinion on this matter might be an interesting read ("Edgar Dijkstra: Go To Statement Considered Harmful" http://wwwens.uqac.c...jkstra_Goto.pdf)

I'm curious about the intent behind the poll in this thread; are you meaning to form an opinion based on the general consensus?
Telastyn
Telastyn
I've used one goto in the say... 18 years I've been programming. It was a throwaway test app that I had to trigger cleanup code before exiting the function and had done it so slapdash that a finally block wouldn't deal with it; and it amused me to write such horrible code.

If you used a goto in production code I would fire you on the spot.
Bregma
Bregma
I use [font="Courier New"]goto[/font]. Quite a bit.

I use it exclusively in object-oriented C programming, because C lacks useful constructs such as RAII and exceptions. It is better to have a forward-jumping goto into a sequence of rollback operations as you initialize members on your constructor code than any other way of handling failures. The use of [font="Courier New"]goto[/font] gives clarity and structure where no other construct can.

For those of you who are too young to understand what Dijkstra wrote, his poins was that alternatives to [font="Courier New"]goto[/font] should be emphasized and chosen in many situations. At the time, such as when I was a student, much code was written in non-structured langauges like FORTRAN IV or BASIC, and the use of [font="Courier New"]goto[/font] was required by the language itself. Most programs were spaghetti code. Dijkstra was involved in designing a new language, one that could be used to teach and to reason about computing -- he was not advocating a dogmatic methodology for future generations.

When a dogmatic anti-goto zealot tells you never to use that control construct, stop and ask for a clarification on the reasons why. If he or she can not tell you any reason other than the ipso dixit of "Dr. Dijkstra wrote a paper saying it was harmful," ignore them and any other advice they give.
Stephen M. Webb
Professional Free Software Developer
Dragonion
Dragonion
in some languages you would be highly restricted if there weren't any "goto"s

I see your point.

I'm curious about the intent behind the poll in this thread; are you meaning to form an opinion based on the general consensus?

The reason I made this poll is because i personally use them exactly this way:

I find them useful to do cleanup in functions that can fail, so I dont have to free all the resources everywhere, I can just goto the end, and put all the frees there

... and I got curious about whether people in general avoid them at all cost, or if there were indeed others who think they are the right solution in some (special) situations.
Antheus
Antheus

I never use goto statements. It's generally unsafe to change the flow of an application in this way. Almost in every situation there are more suitable techniques that are safer, and which won't create spaghetti.


Which is a pointless statement. Unless one writes function bodies which are hundreds of lines long, which is spaghetti code anyway, then goto in any today's language isn't capable of creating such mess anymore.

THIS is spaghetti code referred to by the article and something that isn't realistically possible today. Any compiled code generated by compilers or VMs today looks exactly the same, there is just million times more of it. It wasn't sloppy programming - there just aren't any functions, labels, namespaces, classes or anything. Hence "structured programming" was considered an advancement.

If you used a goto in production code I would fire you on the spot.[/quote]

Which is fine, since I don't want to belong to religious organizations based around dogmas conjured on word-of-mouth lore.

I can't imagine what would happen if someone dared overload an operator.

----
Djikstra has the misfortune of being misquoted ever since he wrote the article. But the context in which was written was different and reasons were long lost by many generations that came in between. He proposed that goto functionality be replaced with higher semantic constructs, such as for and while loops. And later, functions... The horror....

So in that context the question would be: do you ever use goto instead of a for loop?int i = 0;
start:
if (i == 100) goto end;
i++;
goto start;
end:
;
Because when he wrote that, this is what code looked like.

And since people got creative, it went further:int i = 0;
int j = 1;
start:
i++;
if (j %2&& j%3 == 0) goto phase 3
goto phase3;
phase2:
j++;
goto start:
phase3:
goto p;
Oh, right. They didn't have functions either, so p was return address. So the above code would be used like this:0x221: p = 0x223;
0x222: goto start:
0x223:
// and later
0x300: p = 0x302;
0x301: goto start:
0x302:
Pray that you counted the bytes in advance correctly, since inserting a line and running out of space might mean renumber all jumps in code below.

BASIC was really great high level language which had gosub that allowed prameterless function calling as well as looping constructs, thereby eliminating the need for such code. But as gurus would say, a lot of optimization opportunities were lost due to these high-level languages (true to an extent).

BASIC still had numbering problem, so you'd start writing the program with each line as multiple of 10. When new stuff was inserted, you'd stuff it in between, maybe as 15 or 25. And if you ran out and had to renumber, gosubs were suddenly broken since they relied on line numbers. So functions were usually put at some high number, such as 2000, 2200, 2500, leaving enough room in between.

In C, goto can be used idiomatically as error handler.
In C++ there is not much use that cannot typically be replaced using either break or continue, both available in Java as well. It doesn't cause problems with auto-allocation either, compared to setjmp/longjmp which is more commonly found in C.
Java does define goto keyword but it's not implemented.
PHP recently added it, most other languages do not have it.
ProgrammerZ
ProgrammerZ

I find them useful to do cleanup in functions that can fail, so I dont have to free all the resources everywhere, I can just goto the end, and put all the frees there


Isn't that more or less what exceptions are for?
Antheus
Antheus

[quote name='zacaj' timestamp='1312665780' post='4845550']
I find them useful to do cleanup in functions that can fail, so I dont have to free all the resources everywhere, I can just goto the end, and put all the frees there


Isn't that more or less what exceptions are for?
[/quote]

C doesn't have exceptions (or constructors/destructors).

Exceptions might also be non-deterministic and cannot be used for hard real-time system or in a system which needs to behave deterministically with respect to error, so propagation doesn't add extra value beyond error codes.

See Linux kernel coding guidelines which describe the idiomatic error handlers. In C++, one would use objects, preferably RAII in combination with exceptions instead. The non-determinism consideration remains, but is rarely required.
tariqwalji
tariqwalji
Actually in C#, I believe it is valid to use goto statements when dealing with switch statements that share the same code. In C# you cannot do


switch(var)
{

case a:
case b:
case c:
some code...
}

Dragonion
Dragonion
Isn't that more or less what exceptions are for?

In addition to what Antheus wrote about exceptions not existing in C, the concept of goto is actually very natural to the processor, and for that very reason they are usually translated into a single jump instruction, if any:

Goto version

int test (int i)
{
if(i)
goto ERROR;

return 1;

ERROR:
return 0;
}

[source]
?test@@YIHH@Z (int __fastcall test(int)):
00000000: xor eax,eax
00000002: test ecx,ecx
00000004: sete al
00000007: ret
[/source]
Exception version

int test (int i)
{
if(i)
throw(0);

return 1;
}

[source]
?test@@YIHH@Z (int __fastcall test(int)):
00000000: push ecx
00000001: test ecx,ecx
00000003: je 0000001C
00000005: push offset __TI1H
0000000A: lea eax,[esp+4]
0000000E: push eax
0000000F: mov dword ptr [esp+8],0
00000017: call __CxxThrowException@8
0000001C: mov eax,1
00000021: pop ecx
00000022: ret
[/source]
21st Century Moose
21st Century Moose
The objective should always be to have clean, readable, maintainable code that works. Use whatever programming construct is most appropriate on a case-by-case basis to achieve this. Sometimes it's an if, sometimes it's a loop, sometimes an exception handler, sometimes even a dreaded goto. You won't know this until you come to design the code, so don't presume in advance that Thou Shalt Not ever do things a certain way, and always remember that you can sometimes create an even bigger mess by attempting to avoid a particular construct, or by attempting to shoe-horn an algorithm into an unsuitable construct.
Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls. 
Oberon_Command
Oberon_Command

Actually in C#, I believe it is valid to use goto statements when dealing with switch statements that share the same code. In C# you cannot do


switch(var)
{

case a:
case b:
case c:
some code...
}




Actually, that's not quite true in C#.

// you can do this
switch (x) {
case 1:
case 2:
case 3:
// stuff
break;
}

// but not this
switch(x) {
case 1:
//stuff
case 2:
// more stuff
case 3:
// even more stuff
break;
}
_the_phantom_
_the_phantom_

[quote name='ProgrammerZ' timestamp='1312669641' post='4845586']Isn't that more or less what exceptions are for?

In addition to what Antheus wrote about exceptions not existing in C, the concept of goto is actually very natural to the processor, and for that very reason they are usually translated into a single jump instruction, if any:

Goto version

int test (int i)
{
if(i)
goto ERROR;

return 1;

ERROR:
return 0;
}

[source]
?test@@YIHH@Z (int __fastcall test(int)):
00000000: xor eax,eax
00000002: test ecx,ecx
00000004: sete al
00000007: ret
[/source]
Exception version

int test (int i)
{
if(i)
throw(0);

return 1;
}

[source]
?test@@YIHH@Z (int __fastcall test(int)):
00000000: push ecx
00000001: test ecx,ecx
00000003: je 0000001C
00000005: push offset __TI1H
0000000A: lea eax,[esp+4]
0000000E: push eax
0000000F: mov dword ptr [esp+8],0
00000017: call __CxxThrowException@8
0000001C: mov eax,1
00000021: pop ecx
00000022: ret
[/source]
[/quote]

The problem is your two pieces of code do not show the same operational construct; one is error code returning, the other is error throwing. I see the intent but the code is not a true representation of solving the same problem as the exception version does more work.
(Sidebar; technically the code is poor anyway as your latter example shows that 'error' is an exceptional case therefore you should invert the test and assume 'succeed' occurs more often... just sayin' ;))

Personally I'm not against 'goto', however once I stopped coding in BASIC and Assembly and became mainly a C++ coder I have found no practical reason (as yet) to use it in my own code when other methods serve me better.
Telastyn
Telastyn

If you used a goto in production code I would fire you on the spot.


Which is fine, since I don't want to belong to religious organizations based around dogmas conjured on word-of-mouth lore.

I can't imagine what would happen if someone dared overload an operator.
[/quote]

Sorry, I should've clarified. I work currently in C# house. If you're using that language (as opposed to C/basic/etc where options are lessened) and still manage to mangle your design sufficiently that goto is your best option... and then proceed to use goto anyway instead of cleaning up your design; then you've shown yourself as someone not to trust in the codebase.

The same thing would happen if you made a 2000 line method by hand or a class with 100 public parameters. They're not dogma, they're definitive signals that either you don't care or you're a bad programmer.
smasherprog
smasherprog
I agree with Phantom, the use of goto is never actually needed. But, that doesn't mean that it shouldn't be used right?
There is nothing wrong with goto in-of-iitself, and yes goto's are natural to the compiler, and execution flow, on and on.

The problem with goto is that the intent of the code is not clear, which will lead to bugs if it is used often. The whole point behind creating a function is to separate logical pieces of code, and or reuse redundant code. A function shows a clear separation of code from the rest. I suppose a good example would be to try and create a program without using functions, just goto statements. That program would be a very bad program. Now, I realize this is an extreme, but this extreme shows how the use of the goto statement can be bad. If resources must be freed, then a function should be created to free resources and it should be called. In this way, all the freeing of resouces occurs in a single place, so if there is a memory leak, you should be able to find it quickly. A goto statement is bad because it means many more lines of code will have to be altered if a program flow changes. If the goto's are removed, minimal code changes are required because the program is separated into logical parts which are easy to modify on their own.

I realize that people will still use goto's, but it leads to more confusion and bugs than it helps. Ask anyone who has worked on large projects before if the use of goto is a help or a hindrance and I know it will be that goto's do not help in any case what so ever. Programming is about structure and organization, and goto's really do break that concept.

If a person is working on their own code by themselves, use goto all you want, but if you are working on a project with others, do not use goto. I agree with
Telastyn when he said, "If you used a goto in production code I would fire you on the spot." This is soo true
Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.
alvaro
alvaro
I guess I am a heretic, but I use goto in other situations that haven't been mentioned here. The most common is something like this:
for (int i=0; i<n; ++i) {
switch (some_array) {
case 0:
//...
break;
case 1:
if (some_condition())
goto DONE; // Break out of the loop, in a situation where `break' would just break out of the switch block.
break;
//...
}
}
DONE:
//...
smasherprog
smasherprog

I guess I am a heretic, but I use goto in other situations that haven't been mentioned here. The most common is something like this:
for (int i=0; i<n; ++i) {
switch (some_array) {
case 0:
//...
break;
case 1:
if (some_condition())
i=n;// DONE!!!
break;
//...
}
}
//...

Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.