1. 17
  1.  

  2. 8

    Speaking as a C programmer, this is a great tour of all the worst parts of C. No destructors, no generics, the preprocessor, conditional compilation, check, check, check. It just needs a section on autoconf to round things out.

    It is often easier, and even more correct, to just create a macro which repeats the code for you.

    A macro can be more correct?! This is new to me.

    Perhaps the overhead of the abstract structure is also unacceptable..

    Number of times this is likely to happen to you: exactly zero.

    C function signatures are simple and easy to understand.

    It once took me 3 months of noodling on a simple http server to realize that bind() saves the pointer you pass into it, so makes certain lifetime expectations on it. Not one single piece of documentation I’ve seen in the last 5 years mentions this fact.

    1. 4

      It once took me 3 months of noodling on a simple http server to realize that bind() saves the pointer you pass into it

      Which system? I’m pretty sure OpenBSD doesn’t.

      https://github.com/openbsd/src/blob/4a4dc3ea4c4158dccd297c17b5ac5a6ff2af5515/sys/kern/uipc_syscalls.c#L200

      https://github.com/openbsd/src/blob/4a4dc3ea4c4158dccd297c17b5ac5a6ff2af5515/sys/kern/uipc_syscalls.c#L1156

      1. 2

        Linux (that’s the manpage I linked to above). This was before I discovered OpenBSD.

        Edit: I may be misremembering and maybe it was connect() that was the problem. It too seems fine on OpenBSD. Here’s my original eureka moment from 2011: https://github.com/akkartik/wart/commit/43366d75fbfe1. I know it’s not specific to that project because @smalina and I tried it again with a simple C program in 2016. Again on Linux.

          1. 1

            Notice that I didn’t implicate the kernel in my original comment, I responded to a statement about C signatures. We’d need to dig into libc for this, I think.

            I’ll dig up a simple test program later today.

            1. 2

              Notice that I didn’t implicate the kernel in my original comment, I responded to a statement about C signatures. We’d need to dig into libc for this, I think.

              bind and connect are syscalls, libc would only have a stub doing the syscall if anything at all since they are not part of the standard library.

      2. 2

        Perhaps the overhead of the abstract structure is also unacceptable..

        Number of times this is likely to happen to you: exactly zero.

        I have to worry about my embedded C code being too big for the stack as it is.

        1. 1

          Certainly. But is the author concerned with embedded programming? He seems to be speaking of “systems programming” in general.

          Also, I interpreted that section as being about time overhead (since he’s talking about the optimizer eliminating it). Even in embedded situations, have you lately found the time overheads concerning?

          1. 5

            I work with 8-bit AVR MCUs. I often found myself having to cut corners and avoid certain abstractions, because that would have resulted either in larger or slower binaries, or would have used significantly more RAM. On an Atmega32U4, resources are very limited.

        2. 1

          Perhaps the overhead of the abstract structure is also unacceptable..

          Number of times this is likely to happen to you: exactly zero.

          Many times, actually. I see FSM_TIME. Hmm … seconds? Milliseconds? No indication of the unit. And what is FSM_TIME? Oh … it’s SYS_TIME. How cute. How is that defined? Oh, it depends upon operating system and the program being compiled. Lovely abstraction there. And I’m still trying to figure out the whole FSM abstraction (which stands for “Finite State Machine”). It’s bad enough to see a function written as:

          static FSM_STATE(state_foobar)
          {
          ...
          }
          

          and then wondering where the hell the variable context is defined! (a clue—it’s in the FSM_STATE() macro).

          And that bind() issue is really puzzling, since that haven’t been my experience at all, and I work with Linux, Solaris, and Mac OS-X currently.

          1. 1

            I agree that excessive abstractions can hinder understanding. I’ve said this before myself: https://news.ycombinator.com/item?id=13570092. But OP is talking about performance overhead.

            I’m still trying to reproduce the bind() issue. Of course when I want it to fail it doesn’t.

        3. 5

          The core of my job involves having exact control over object lifetimes, ease of manipulating data structures accessed by drivers/the hardware, ability to move things around with zero copying (and knowing that it won’t suddenly get copied if I change some code somewhere and suddenly “oops, no move constructor!”), zero garbage-collection delays, and the ability to easily reason about the number of context switches a given piece of code will have.

          There isn’t a better language for that than C.