Why do some kernel programmers use goto instead of simple loops?

When I learned C, the teacher told me all day: "Don't use goto, it's a bad habit, it's ugly, it's dangerous!" etc.

Why, then, some kernel programmers use goto , for example, in this function , where it can be replaced with a simple

 while(condition) {} 

or

 do {} while(condition); 

I do not understand this. In some cases, it's better to use goto instead of while / do - while ? And if so, why?

+48
c linux loops linux-kernel goto
Oct 21 '12 at 18:58
source share
3 answers

In this example, I suspect that it is about retrofitting SMP support in code that was originally written in a secure way that does not support SMP. Adding the goto again; path goto again; much simpler and less invasive than restructuring a function.

I can’t say that I like this style a lot, but I also think that he mistakenly avoided goto for ideological reasons. One of the special cases of using goto (other than this example) is that goto is only used to move forward in a function, not backward. This usage class never leads to loop constructs arising from goto , and it is almost always the easiest and clearest way to implement the necessary behavior (which is usually cleared and returned on error).

+27
Oct 21
source share

Historical context:. We must remember that Dijkstra wrote Goto Wased Harmful in 1968, when many programmers used goto as a replacement for structured programming ( if , while , for , etc.).

It is 44 years later, and it is rare to find this use of goto in the wild. Structured programming has long won.

Case Analysis:

Sample code is as follows:

  SETUP... again: COMPUTE SOME VALUES... if (cmpxchg64(ptr, old_val, val) != old_val) goto again; 

The structured version is as follows:

 SETUP... do { COMPUTE SOME VALUES... } while (cmpxchg64(ptr, old_val, val) != old_val); 

When I look at the structured version, I immediately think, "This is a cycle." When I watch the goto version, I think of it as a straight line with the argument β€œtry again” at the end.

The goto version has both SETUP and COMPUTE SOME VALUES in the same column, which emphasizes that most of the time the control flow goes through both. The structured version puts SETUP and COMPUTE SOME VALUES in different columns, which emphasizes that control can go through them differently.

The question is, what emphasis do you want to put in the code? You can compare this with goto for error handling:

Structured version:

 if (do_something() != ERR) { if (do_something2() != ERR) { if (do_something3() != ERR) { if (do_something4() != ERR) { ... 

Go to version:

 if (do_something() == ERR) // Straight line goto error; // | if (do_something2() == ERR) // | goto error; // | if (do_something3() == ERR) // | goto error; // V if (do_something4() == ERR) // emphasizes normal control flow goto error; 

The generated code is basically the same, so we can consider it as a typographical problem, such as indentation.

+56
Oct 21 '12 at 19:26
source share

A very good question, and I think that only the author can give a definitive answer. I will add my assumptions by saying that it could start by using it to handle errors, as explained by @Izkata, and the gates were open to use it for basic cycles as well.

In my opinion, the use of error handling is legal in system programming. The function gradually allocates memory as it progresses, and if an error is detected, it will goto corresponding shortcut to free resources in the reverse order from this point.

Thus, if an error occurs after the first placement, it moves to the last error label to free up only one resource. Similarly, if an error occurs after the last selection, it goes to the first error label and starts from there, freeing all resources to the end of the function. This error handling pattern still needs to be used carefully, especially when it is strongly recommended that code, valgrind, and unit tests be modified. But this is perhaps more readable and maintainable than alternative approaches.

One of the golden rules for using goto is to avoid the so-called spaghetti code. Try drawing lines between each goto and the corresponding label. If you have an intersection of lines, you crossed the line :). This use of goto very difficult to read and is a common source of difficult-to-track errors, as they are found in languages ​​like BASIC that use it to control the flow.

If you make only one simple cycle, you will not get the intersection of lines, so it is still readable and easy to maintain, becoming in many ways a matter of style. However, since they can be just as easily done using the loop keywords provided by the language, as you pointed out in your question, I still recommend that you avoid using goto for loops, simply because the for , do/while or while constructs more elegant in design.

0
Jun 26 '19 at 11:05
source share



All Articles