1. 8

    The last two paragraphs are really important.

    Be knowledgeable about what’s actually in the C and C++ standards since these are what compiler writers are going by. Avoid repeating tired maxims like “C is a portable assembly language” and “trust the programmer.”

    Unfortunately, C and C++ are mostly taught the old way, as if programming in them isn’t like walking in a minefield. Nor have the books about C and C++ caught up with the current reality. These things must change.

    There’s no excuse for invoking UB anymore. Either you have a use case that absolutely requires the ridiculous features of C and C++ (in which case you better be damn sure you’re not stepping on a mine), or you’re performing malpractice by using an inappropriate language.

    1. 20

      I think a lot of people don’t understand just how easy it is to write code with undefined behavior in it. Because C and C++ programmers often aren’t taught about it when learning the language, when they do hear about it, they think “oh, that’s something that other people’s code has to deal with. I write good code, and I’m this doesn’t affect me. If it did, I would have been taught it when I learned the language.”

      This is why I value John Regehr’s work so much. He’s been beating the drum of UB as a danger to take seriously for a while, and I’m really happy to see his stuff getting more traction in the programming community.

      I’m going to be teaching a class on C programming soon, and I’ll absolutely put UB front and center in it; maybe with people like John Regehr pushing for better education and better tooling, more people will do the same.

      1. 1

        What resources do you guys recommend to learn C?

        1. 2

          I think anyone trying to learn the language properly needs at a very minimum, the (draft) standards. There are far too many books, tutorials, etc. that just gloss over important details or make grossly misleading simplifications.

          Then read (good) man pages for library functions. Read code. Write code. Lots of code. Keep an eye out on some projects and watch it as bugs get fixed. Try to understand the bug and the fix.

          A book might or might not help. I’ve only read one book on C – Expert C Programming. It was an ok read but I didn’t learn too much from it. A newcomer might find it more useful however.

          EDIT: taossa ch6 is also a great read for anyone doing C. http://ptgmedia.pearsoncmg.com/images/0321444426/samplechapter/Dowd_ch06.pdf

          Alternative link: https://trailofbits.github.io/ctf/vulnerabilities/references/Dowd_ch06.pdf

      2. 5

        I could agree with that, but there’s a lot of code written 20 years ago or more. And it’s not so easy to simply use an old compiler. Want to run arm64? Get a new compiler. And the arm64 platform would be rather less interesting if you simply banned all old software.

        1. 1

          That’s a great point about old software being used on new hardware. In such cases, would it be better to use a compiler with defined (and safe) behavior in all UB? (Presumably the performance of the new hardware is better than the old hardware it was originally written for, so you could afford things like symbolic addresses, bounds checking, “gcc-x86-like” overflow, etc.)

          It still seems like it would be better to fix the old software so it doesn’t invoke UB, but we all agree how hard that is.

          1. 2

            There’s quite a lot of UB in C, much of it designed so that different platforms can each use their “native” support for various things like addressing modes, alignment, etc. If you really wanted to define all behavior to be essentially equivalent to what gcc on x86 traditionally does, this would amount to a pretty significant runtime layer on non-x86 platforms emulating x86-like behavior. At which point why even use C, not something that actually has a portable runtime and/or bytecode defined from the start? I guess purely for legacy software it’d make sense.

            1. 1

              That’s a great point about old software being used on new hardware. In such cases, would it be better to use a compiler with defined (and safe) behavior in all UB?

              There are so many people proposing this that eventually one might start to believe it is actually a thing.

              But I have not seen such a compiler and I doubt I ever will.

        1. 1

          off-topic: what’s this keyboard model tho?

          1. 2

            Vortex POK3R with Cherry MX Clear switches and DSA Granite caps :)

            Played around with fancier stuff but at the end of the day I was happiest with the look and feel of this one.

          1. 4

            Summary : configuration files evolve into impromptu programming languages over time. Just use a programming language to configure a program.

            I think the same is valid for languages like SQL: you make a small language to solve a domain-specific problem, but the problem’s scope is too broad, leading to the creation of not-so-well-designed programming languages like PL/SQL.

            1. 13

              I think the same is valid for languages like SQL: you make a small language to solve a domain-specific problem, but the problem’s scope is too broad, leading to the creation of not-so-well-designed programming languages like PL/SQL.

              I wouldn’t want to imagine a world though where everyone writes their SQL queries in a turing-complete, imperative programming language, let alone optimize them. SQL is one of the best examples where favoring declarative style has lead to huge improvements outside of edge-cases. Still lots of footguns around, but much less then in most programming languages.

              And PL/SQL is a good example of how things can go wrong :).

              1. 2

                I wouldn’t want to imagine a world though where everyone writes their SQL queries in a turing-complete, imperative programming language, let alone optimize them.

                SQL itself is turing-complete already though. ;)

                1. 2

                  So is Magic: the Gathering.

                  Turing completeness can arise by accident. It doesn’t make an environment where you’d actually use that property.

            1. 0

              I would like to see an implementation using Rust.

              1. 1

                Reading the “Programming Elixir 1.2” book by Dave Thomas, as (the backend of) the game I’m currently working on is mostly written in Elixir.

                1. 23

                  It’s interesting that he suggests that you wouldn’t write a Haskell app on PS4. I happen to be in gamedev, and although the common wisdom is that everything in this field is hyper-bummed hand-tuned C++ and assembly, more and more those languages are retreating to the core engine and in some cases fragmenting and dissipating completely. Most (by any metric) games these days are written in pure C# on Unity. Unity itself is written in C++, but few companies splurge for the source license. Even most of the existing top tier games (world of warcraft, call of duty…) are written primarily in an embedded extension language (lua or similar) that exposes primitives at a higher level to the game designers and scripters.

                  But intriguingly, even that is undergoing revision – one designer I interviewed recently had been working on a recently released top-tier AAA game in the running for best game of 2016, and he said that their engine was literally Racket all the way down to the metal, from DSLs used to create the scripting interface all the way down to the shader compilers. And another dev I interviewed from another top tier AAA gaming company also said their engine was almost entirely Racket as well now. I almost didn’t believe it until he showed me screenshots of the debug interface.

                  Similarly, I know from personal experience that many mobile game studios are using or experimenting with erlang on the backend – including me! So the notion that these languages are so esoteric as to be implausible isn’t informed by facts on the ground; at least, not this particular ground.

                  1. 3

                    IIRC, Crash Bandicoot was written using a Scheme dialect.

                    1. 3

                      one designer I interviewed recently had been working on a recently released top-tier AAA game in the running for best game of 2016, and he said that their engine was literally Racket all the way down to the metal, from DSLs used to create the scripting interface all the way down to the shader compilers. And another dev I interviewed from another top tier AAA gaming company also said their engine was almost entirely Racket as well now.

                      That’s unexpected! Can you mention the game and company names?

                      1. 9

                        I’m speculating without any direct knowledge, but Uncharted 4 was recently released to critical acclaim and was developed by Naughty Dog, who famously used AOT-compiled Lisp to write games like Crash Bandicoot and Jak and Daxter.

                        1. 1

                          Thanks for the reference.

                      2. [Comment removed by author]

                        1. 10

                          Uncharted 4 and a game I can’t disclose.

                        2. 1

                          I once worked at a company that wrote extensive amounts of PHP to host websites. One day I suggested that we rewrite the entire core of the infrastructure in order to make it faster and more stable, but all I got back was some grumbles about how much time it would consume.

                          I’m also soon going to be working somewhere where Angular is the core of the frontend, but I have no idea how I could convince them to consider switching to React without breaking down barriers and starting fires.

                          1. 4

                            I don’t know what your specific situation was like, but I think the response you got back from the PHP company was valid. A big rewrite is something that one should be able to make a really good ROI on or be pulling in enough money to cover a failure if it happens. They do need to happen (probably more often than they should), but there should be a pretty healthy dose of “no way” in order to elucidate a compelling reason.

                        1. 3

                          São Paulo, Brazil.

                          1. 2

                            It’s 56 years old, to be exact.

                            1. 3

                              I guess that’s an important step to an actual “containerization” offered by Docker. I’ve never given too much attention to Unikernels, but now it’s getting pretty interesting. Projects like Tor, Qubes OS and even Mirage OS could take many different advantages that Docker gives, and I would like to see how ARM-based SoCs will explore that kind of “virtualization”.