1. 65

  2. 16

    Backward compatibility: when code already written is more important than code yet-to-be written; thereby picking ongoing pain for new developers over a fixed amount of pain for existing ones.

    1. 22

      Backwards compatibility: when developers can trust that code they write tomorrow won’t be broken by a language spec change two years from now.

      1. 18

        …instead it’ll be broken by a subtle compiler change that was within the spec, but the old compiler didn’t warn about this possibility.

        1. 4

          Had something exactly like this moving a half million LOC codebase at work from gcc 4.8 to 7. It’s literally nightmare fuel upgrading a compiler for this work project.

          1. 1

            That’s what testing is for.

            1. 1

              Testing isn’t all encompassing and never can be.

            2. 1

              That’s what tools like Frama-C are for, as well as things like the Clang static analyzer or ubsan.

              1. 9

                I’d rather have a language where I don’t need such tools.

                1. 2

                  Sure – for most programs a high level garbage collected language with a good type system is the right choice.

                  However, the tooling for C tends to allow for more safety at compile time than most languages, if you decide to use it to its full extent. Most people don’t, and just wing it – but if you want to put in the effort and do the annotation work, you can statically guarantee, for example, that you’ll never run out of memory at runtime, overflow the stack, or have accidentally non-terminating loops.

                  SPARK, as far as I’m aware, is the major competition if you want high assurance code. It probably does the job better, though I haven’t really had a chance to experiment with it.

                  1. 1

                    I was thinking about Rust.

            3. 10

              Backwards compatibility: forcing your kids and grandchildren to make the same mistakes you did.

          2. 9

            … and this is why, to this day, I look at every non-trivial C program and its programmer as I would a hand grenade without its pin and the grinning madman holding it and insisting I can trust him.

            1. 7

              Either I didn’t get some kind of irony, or this is a really frustrating read. Especially this part:

              We will not introduce warnings into your old code, even if that old code could be doing something dangerous.

              I’m mostly a Java dev so I love me some backwards compat but this is ridiculous.

              It sounds like people and organizations who are unwilling to fix their bad code are holding the whole ecosystem back. Why can’t they just stay on the old compiler versions then?

              Sad to see a language strangling itself with its old baggage.

              1. 1

                What if some of the largest users of a language also bankroll it? They won’t relegate themselves to older versions.

              2. 7

                That article is better than I expected. Judging by the title, I expected yet another rehash of mistakes made in C programs.

                It’s an interesting problem when the standard can’t afford to outlaw existing “working” code even when it works only by accident.

                This reminds me of the proposal for C++ to change priorities to be more forward-looking than backwards-compatible, which could lead to Google forking C++: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2137r0.html

                1. 6

                  What’s crazy to me is that they can’t even put warnings up on existing code. The perspective of the article makes it sounds like correctness in C is basically a multi-party agreement to Look the Other Way. Yikes!

                  Hopefully at least Clang and/or GCC will still add these warnings behind another flag?

                  1. 4

                    A C compiler can add warnings, and many do, but they don’t enable new warnings by default because of the noise it introduces. My favorite example of this is clang—on a lark, I enabled every warning it has (I forgot the version, but this was in the past year or two). I got the warning “padding added to structure blah blah”. Okay, let’s switch to packed structures. I then got the warning “no padding in structure blah blah”. I just couldn’t win with clang. But I can see the rational for adding both warnings—it’s just that you have to pick one or the other but not both.

                  2. 1

                    though that might change once google is completely switched go..

                  3. 3

                    To what extent do these issues also affect other “legacy” languages, e.g. FORTRAN?

                    Also, apart from security concerns, do these issues also raise problems for scientific programming tasks? For example: there are many old scientific programming code bases written in FORTRAN or C, which are considered to be the gold standard in performance. Should one be weary of about their correctness?

                    1. 1

                      To what extent do these issues also affect other “legacy” languages, e.g. FORTRAN?

                      Fortran has similar backward compatibility issues.
                      The COBOl-85 standard was initially rejected because of a lack of backward compatibility.

                      Also, apart from security concerns, do these issues also raise problems for scientific programming tasks? For example: there are many old scientific programming code bases written in FORTRAN or C, which are considered to be the gold standard in performance. Should one be weary of about their correctness?

                      I’m leery of any app that doesn’t have a test suite and many apps that do.
                      Undefined behavior is common in C applications; I’m not sure about Fortran.
                      The app may have worked at the time but modern optimizers are more likely to exploit undefined behavior.

                    2. 2

                      Because it actually believes you meant what you said. Because a programmer is a kind of professional who tells computers what to do, not the other way around.

                      1. 11

                        Software flaws have real material costs which often manifest as sprawling negative externalities, and C makes writing complex software without these flaws basically impossible. Consider the costs of heartbleed, the Cloudflare memory disclosure bug, or every bug in SMS/MMS parsing that can brick users’ phones.

                        Professionals in other lines of work use tools that prevent mistakes all the time, refusing to use tools that let you work safely because you need to stroke your ego is amateur hour.

                        1. 6

                          With that argumentation you can throw out all of the PLT advancements of the last decades (type systems, formal verification, contracts, …) because why would anyone need that if the computer already does what I say? I vehemently disagree with you, making the computer “do what I say” is not enough to produce working and correct software in any non-trivial capacity.

                          1. 1

                            No, not at all. There are many great advances out there to make it easier to say what you mean, all of which are valuable. But, once you’ve laid that framework, once you’ve defined the language, if the programmer says something that can be given a valid interpretation within the documented rules of the game, it’s the computer’s responsibility to do exactly that thing.

                            (Having tools that check for mistakes, i.e. linters, is of course fair game.)

                          2. 5

                            which is why we all write assembly, instead of using languages that might rewrite our code behind our back or check whether we made one mistake in thousands of lines of code, being professionals who by definition are all knowing and error-free.

                            1. 1

                              Only when it comes in handy :)

                            2. 2

                              Totally underrated view.

                              I personally didn’t sign up for this mindset that everyone just writes buggy code (read:low quality code) and the we throw linters, static analysis tools, compiler warnings and whatnot at it. Then quality should mysticaly spring to life like ghosts separating from dead bodies in horror movies, I suppose.

                              There must be a limit to how many errors are reasonable. “There’s no bug free code” doesn’t mean that anything goes.

                            3. 2

                              Doesn’t the dog/cat example violate the strict aliasing rule?

                              1. 4

                                I’m not sure — is the rule taking effect at the time of pointer creation, or use?

                                In either case, if compilers accept that code, by Hyrum’s Law, it doesn’t matter what the standard thinks about it.

                                1. 2

                                  An object can only have its stored value accessed via an lvalue of a compatible type. (C99 s. 6.5 p 7)

                                  It is perfectly fine to merely copy the value of a pointer into an lvalue of an incompatible type as long as it is never dereferenced – although I cannot think of a reason why you would.

                                  1. 3

                                    There’s no requirement in C that sizeof(X*) and sizeof(Y*) are the same, so this might not be possible. char* and void* must be large enough to hold pointers to anything, but C on a sufficiently weird architecture pointers may be different sizes depending on the size of the values. On machines that have word-addressable memory, most types are just addresses but char* and void* are both an address plus a mask or offset.

                                    This doesn’t matter for any mainstream architectures.

                                    1. 2

                                      I won’t call it good practice, but you can do this to store a pointer-to-X in a pointer-to-Y as long as you know that the latter is never dereferenced as such. I.e. you always convert it back to pointer-to-X before dereferencing it. You could for example (ab)use an unused structure member to hold a different kind of pointer than its declared type.

                                  2. 2

                                    That rule is commonly misunderstood. It’s permissible to convert a pointer to one type to a pointer to another type, it’s not permissible to dereference a pointer if it points to an “object” (that’s the terminology of the standard) of the wrong type (with some exceptions/allowances).

                                    If I remember rightly converting a pointer from one type to another results in an implementation-defined value anyway, i.e. it doesn’t even necessarily point into the same object. Of course, with your typical compiler, it does.

                                  3. 2

                                    As a side note I’ve also become the Project Editor for C so before you take this as an uninformed rant of a person too lazy to “make things better”, let me assure that I am, indeed, incredibly invested in making sure C can begin to meet the needs of developers without needing 50 vendor-specific extensions to build remotely nice/usable libraries and applications.

                                    Okay, so probably not lazy, but it’s hard not to see this as uninformed. The example is a constraint violation and required to produce a diagnostic. It’s certainly not guaranteed to translate. In fact, a compiler that translates this without warnings is not—by fiat—a C implementation.

                                    Fair enough, it’s still bullshit that compilers do this by default, but it’s not like the standard didn’t try.

                                    1. 1

                                      Thank you; this was really interesting.

                                      The humor and lightheartedness were sometimes more distracting than successful in their goals, however.