News for hackers. Stuff that matters.
Re:Linux: Using goto In Kernel Code (2003) by jiggawatts on Saturday July 17, 2021 @06:18AM (#27864814)
I found this paragraph interesting in hindsight, 18 years on from when this discussion occurred:

> We keep lowering the bar for technical prowess, it seems; if something has the potential to be used "wrong", high-minded designers remove the offending syntax rather than find or train competent programmers. This is why Java removes pointers (among other things) -- it's not that pointers aren't useful or efficient, it's that they require discipline from programmers.

It turns out that "discipline doesn't scale", and programmers have not been able to write substantial amounts of reliable and secure software using pointers. Not Linus, not the BSD maintainers, not the OpenSSL team, not anyone. Not even with C++20 and a tool bag full of fuzzers and linters.

Meanwhile, huge amounts of quite safe Java and C# code keep happily ticking along -- exposed to the internet -- often needing patches only for the C/C++ modules that they include as a part of some framework!

One thing I've learned in my old age is that speed limits aren't there for you. They're there for the bad drivers. If you raise the speed limit, more accidents will happen, even if you can handle the speed. More accidents will happen to you, even if you never personally crash your car. Other people can hit you! https://youtu.be/a9UFyNy-rw4?t=179

In the same way, we programmers don't exist in a vacuum. We use vastly more code written by other people than we have written ourselves. Even Linus has personally touched less than 1% of the code it takes to start up a web browser on Linux and load a web page from a Linux web server. See the "30 million line problem": https://caseymuratori.com/blog_0031

To summarise: I've learned that the ecosystem matters, and that we have to optimise for the average case, because that's where the majority are in a Bell curve.

Re:Linux: Using goto In Kernel Code (2003) by inshadows on Saturday July 17, 2021 @06:28AM (#27864842)
This thread isn't about safety though. It's about readability (spaghetti code). IMHO gotos in C when used for for dealing with errors at the end of the function make the code clearer.
Re:Linux: Using goto In Kernel Code (2003) by jiggawatts on Saturday July 17, 2021 @06:49AM (#27864911)
I get that, but the comment was specifically about pointers (not gotos or structure), and is interesting in general from a historical perspective.

The "goto" keyword is similarly dangerous. I've seen very good arguments for leaving it out, and generally poor arguments for keeping it in a language. "I can use it safely" is not a good argument, because it's just like Jim Jefferies' standup routine linked above: "Why should I have my guns taken away from me?"

An example of a good argument for structured programming is the talk "The Forgotten Art of Structured Programming - Kevlin Henney [C++ on Sea 2019]": https://www.youtube.com/watch?v=SFv8Wm2HdNM

Similarly, this article makes a very good argument that concurrent or async code is essentially the "goto spaghetti reinvented, but even worse", and that Structured Concurrency is the solution: https://vorpus.org/blog/notes-on-structured-concurrency-or-g...

Re:Linux: Using goto In Kernel Code (2003) by chrismorgan on Saturday July 17, 2021 @07:06AM (#27864986)
> “I can use it safely” is not a good argument

Rust could comparatively easily implement goto, and it’d be unconditionally safe (as regards memory safety). I’d even honestly like it to, mostly just because it’s possible rather than because it’d be useful—most prominent goto patterns can be expressed better in other ways in Rust, e.g. RAII (destructors) instead of goto cleanup, and break/continue let you emulate any structured uses of goto. (I live in hope that https://github.com/rust-lang/rust/issues/48594 will one day land, so you can use break to skip the remainder of a labelled block, no loop required.)

Re:Linux: Using goto In Kernel Code (2003) by jiggawatts on Saturday July 17, 2021 @07:20AM (#27865042)
Read the articles I linked. This is essentially impossible, because Rust has gained features that C doesn't have by giving up goto. Adding goto back in would require those features to be removed, or to be watered down dramatically.

You wouldn't be able to goto into or out of most (all?) blocks that would change ownership, for example.

Re:Linux: Using goto In Kernel Code (2003) by chrismorgan on Saturday July 17, 2021 @09:03AM (#27865487)
No, not impossible at all; it will just reject any that would be memory-unsafe due to problems with borrow lengths, potentially undefined variables, and things like that. I never said you could goto absolutely anywhere; plenty of gotos are patently unsafe, and Rust would duly reject them.

Rust currently checks borrows using control-flow graphs (though I believe the plan is for that to change, and the replacement might make life harder for implementing goto, I don’t know). Rust’s mid-level intermediate representation (MIR) actually has goto. In a control-flow graph, goto is just adding new edges, and it’s comparatively simple to make it work.

Re:Linux: Using goto In Kernel Code (2003) by ByteJockey on Saturday July 17, 2021 @08:22AM (#27865298)
That's not that much different than C. C's goto is already limited compared to the actual jump instruction because you can't cross function boundaries because of the restrictions C puts on you.
Re:Linux: Using goto In Kernel Code (2003) by varajelle on Saturday July 17, 2021 @08:21AM (#27865294)
Why not? C++ still has goto despite also having RTTI. One just need to restrict a bit where we can jump.
Re:Linux: Using goto In Kernel Code (2003) by aix1 on Saturday July 17, 2021 @11:41AM (#27866548)
Do you mean RAII?
Re:Linux: Using goto In Kernel Code (2003) by afiori on Saturday July 17, 2021 @07:11AM (#27865005)
I would also like continue to work that way, so that every (labelled) block can be freely looped and exited (with a value)
Re:Linux: Using goto In Kernel Code (2003) by chrismorgan on Saturday July 17, 2021 @07:16AM (#27865019)
I don’t think I’d want continue to work on a block. Repeating the block seems different from leaving the block early (which can already be done with return or with panicking). I think it’s better to need to write it as a loop before you can continue.
Re:Linux: Using goto In Kernel Code (2003) by afiori on Monday July 19, 2021 @04:38AM (#27880404)
I completely agree, In rust looping has important semantics with regards to lifetimes and ownership so the continue part would be a bad idea. I think it would be cool in something like javascript (if blocks could return values...)
Re:Linux: Using goto In Kernel Code (2003) by inshadows on Sunday July 18, 2021 @05:18AM (#27871673)
You haven't mentioned anything specific about dangerousness of goto. The fact that you heard some conclusion is irrelevant, unless you pass the reasoning behind it. If goto is dangerous, why isn't if statement dangerous.

And about async code: Have fun writing bare metal code with that. Because, you know, your compiler will spit gotos anyway, and unlike gotos you write, you'll have little control over that.

Re:Linux: Using goto In Kernel Code (2003) by Spivak on Saturday July 17, 2021 @11:33AM (#27866482)
Basically all modern programming control flow paradigms are about finding all the safe patterns of goto and setjmp.

Everyone agrees about loops, try catch for goto err; is near ubiquitous, defer and context managers are popular for goto cleanup;, throw is setjmp up the stack, coroutines are setjmp for multitasking.

Re:Linux: Using goto In Kernel Code (2003) by mkcg on Saturday July 17, 2021 @07:16AM (#27865022)
goto statements are also very useful to parse, compress and uncompress data in the critical loop.
Re:Linux: Using goto In Kernel Code (2003) by gajjanag on Saturday July 17, 2021 @11:42AM (#27866556)
> It turns out that "discipline doesn't scale", and programmers have not been able to write substantial amounts of reliable and secure software using pointers. Not Linus, not the BSD maintainers, not the OpenSSL team, not anyone. Not even with C++20 and a tool bag full of fuzzers and linters.

Well, Google has 100s of millions of lines of C++ that power much of the internet. They certainly have no intention of getting rid of this code, and have deemed the tradeoff worthwhile. Yes, in theory this C++ codebase might not be the most reliable or secure, but their practices are certainly scalable and battle tested. Not saying it is easy, but it is certainly possible to build an ecosystem around C++ with fuzzers/linters/whatever to reach an "acceptable" level in practice.

> Meanwhile, huge amounts of quite safe Java and C# code keep happily ticking along -- exposed to the internet -- often needing patches only for the C/C++ modules that they include as a part of some framework!

Not necessarily. Plenty of null pointer exceptions in production Java code that bring down systems. Yes, they are "safe" but I don't think the tens of millions of customers affected appreciate such subtle nuances: the consequences are the same for them.

I agree that there can be more severe consequences due to the lack of "safety" from exploits, privilege escalation, and what not. But with stuff like sandboxing, the broader ecosystem, etc the decision isn't as simple as your argument might suggest.

Re:Linux: Using goto In Kernel Code (2003) by pjmlp on Sunday July 18, 2021 @02:58AM (#27871203)
That is exactly the reason why Google is pushing for wide adoption of hardware memory tagging as the ultimate solution to fix that C and C++ code, because the dead corpses from battle testing have proven it is not enough.

https://source.android.com/devices/tech/debug/tagged-pointer...

https://security.googleblog.com/2019/08/adopting-arm-memory-...

https://threatpost.com/google-arm-android-bugs-memory-taggin...

https://source.android.com/devices/tech/debug/hwasan

Google also paid for the effort to remove C99's VLAs from the Linux kernel.

https://www.phoronix.com/scan.php?page=news_item&px=Linux-Ki...

Google is also the company that started the effort to adopt Rust in the Linux kernel.

https://security.googleblog.com/2021/04/rust-in-linux-kernel...

So they definitely know how much money it costs them to keep C and C++ around, and are taking actions to reduce that monetary cost related to fixing security bugs.

On the other hand, they just introduced the Android Game Development Kit, with C and C++ APIs.

https://developer.android.com/games/agdk

Re:Linux: Using goto In Kernel Code (2003) by Zababa on Saturday July 17, 2021 @01:18PM (#27867259)
"discipline doesn't scale" is precisely why I think Robert Martin is missing the point with most of his ideology. His solution to everything seems to be "more discipline", but things don't work that way. I also find this incredibly short-sighted in an industry that can so easily build tools. Why be disciplined about formatting when you can build an autoformatter?
Re:Linux: Using goto In Kernel Code (2003) by shaggie76 on Saturday July 17, 2021 @08:32AM (#27865328)
> "discipline doesn't scale"

Brilliant observation!

Re:Linux: Using goto In Kernel Code (2003) by jiggawatts on Saturday July 17, 2021 @09:03AM (#27865482)
I can't take credit. I got that phrase from the article linked to from this discussion: https://news.ycombinator.com/item?id=24834965
Re:Linux: Using goto In Kernel Code (2003) by dmatech on Saturday July 17, 2021 @02:39PM (#27867814)
Discipline can scale, but only among very smart and careful programmers. If you're going to have a one-size-fits-all standard that expects to include novice programmers, it can't include anything dangerous.

Even smart and careful programmers make mistakes, though, and they don't use goto for laughs. Likewise, even a novice programmer can probably use it safely in a small function.

Re:Linux: Using goto In Kernel Code (2003) by smitty1e on Saturday July 17, 2021 @10:11AM (#27865878)
I'd vary that to say: "Everything has a learning curve."

I can have disciplined new hires, but they don't know what they don't know yet about what is at stake.

Re:Linux: Using goto In Kernel Code (2003) by chapium on Saturday July 17, 2021 @10:07AM (#27865846)
This comment is more insightful than 90% of blogs. If you had one, I'd follow it.
Re:Linux: Using goto In Kernel Code (2003) by mmcgr on Sunday July 18, 2021 @03:00AM (#27871209)
If I understand right, this in effect seems to be saying that languages can only permit what the median developer can handle. Am I right?
Re:Linux: Using goto In Kernel Code (2003) by jiggawatts on Sunday July 18, 2021 @06:51AM (#27871985)
I don't want to use the phrase "can permit". Rust and C# have escape hatches, like the "unsafe" keyword. You can write pointer-based code in C#, but the language actively discourages it. The "happy path" is safe code. If you poke through the standard library, you'll notice that there's quite a bit of pointer arithmetic going on, either for interop or performance. On average though, 99.99% of C# code that has been written is safe[1], which is why total beginners can write an ASP.NET website, put it on the Internet, and not get hacked.

The problem with languages like C and C++ is that that the "happy path" is unsafe, unstructured, or an unexpected footgun. There's article after article written about how compilers do bizarre optimisations based on undefined behaviour.

Everyone writing a significant volume of C code is writing code littered with gotos, because as Linus said, it's the only terse way to handle error conditions in C. In C#, Java, and Rust there are structured and safe ways to handle errors (exceptions and the '?' operator). No need for liberally sprinkling code with goto.

Linus rightly makes the claim that "nothing is as good as C" at performance, or low-level control. In the past, this was entirely correct. But these days, even high-level VM-based languages like C# are acquiring features that give C++ a run for its money, and Rust is very close to C++ in performance but much safer.

[1] Memory safe at least. Most C# code is also unlikely to leak resources, unlike most C/C++ code.