Live data from Hacker News

“C is how the computer works” is a dangerous mindset for C programmers

words.steveklabnik.com

151–160 of 387 posts

Re: “C is how the computer works” is a dangerous mindset for C programmers

#151

It's far past time to put C to bed. D, Go, Java, Zig, etc. are all languages that one can use to do approximately C-like things without as much danger. I am tired of seeing a literal Twitter feed of memory unsafety security bugs [0]. We can do better. [0] https://twitter.com/LazyFishBarrel

Good luck rewriting all the programs that are written in C without introducing new security problems.

Feel free to peruse the Twitter feed that I linked; if most bugs are due to memory corruption, then literally rewriting in place may still be a net negative in terms of total bug count! This is the main argument of Zig [0]; they offer technologies to incrementally rewrite C projects in Zig without losing compatibility. Their compiler can compile C code [1] just like GCC or Clang can.

[0] https://ziglang.org/

[1] https://andrewkelley.me/post/zig-cc-powerful-drop-in-replace...

Re: “C is how the computer works” is a dangerous mindset for C programmers

#152

Earlier quoted context omitted.

No, reading uninitialized memory in C is UB.

As far as I know (and I could be wrong), reading uninitialized memory in C is not UB, but gives an indeterminate value, which may be either an unspecified value or a trap representation. If it is a trap representation, accessing it is indeed UB, but if all possible values of your memory are valid, e.g. if you have an unpadded integer where every bit representation means something valid, then it is not UB, though it i…

Not a C expert, just reading what I can find online:

This page says value is indeterminate, which is either unspecified or a trap, as you say: https://wiki.sei.cmu.edu/confluence/display/c/EXP33-C.+Do+no...

But.

This part says that reading an indeterminate value is, in fact, undefined behavior (line 11 in the table): https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+...

Re: “C is how the computer works” is a dangerous mindset for C programmers

#153

Earlier quoted context omitted.

No, reading uninitialized memory in C is UB.

As far as I know (and I could be wrong), reading uninitialized memory in C is not UB, but gives an indeterminate value, which may be either an unspecified value or a trap representation. If it is a trap representation, accessing it is indeed UB, but if all possible values of your memory are valid, e.g. if you have an unpadded integer where every bit representation means something valid, then it is not UB, though it i…

That's the way I think it _should_ work, but sadly does not. For instance, see https://godbolt.org/z/ent-xp

Re: “C is how the computer works” is a dangerous mindset for C programmers

#154

Earlier quoted context omitted.

Microcode is not used for the majority of operations. Are you confusing it with micro-ops?

Maybe you have a different definition in mind than I do? I'm using microcode to mean sequences of micro-ops. Wikipedia [0] seems to agree, "the microcode is a layer of hardware-level instructions that implement higher-level machine code instructions or internal state machine sequencing in many digital processing elements". My understanding is that with a couple exceptions (IIRC mov and zeroing xor are treated special…

I don't have the patience to go fix Wikipedia, but microcode is a patching system (it's what "processor microcode updates" means). Most of the time, that's adjusting chicken bits and other flags. Instructions can be implemented in microcode, but they are really, really slow so it's typically done for security reasons or to emulate some new features that don't require fast performance.

Micro-ops are part of the micro-architecture of the processor, and are in hardware. They are not patchable and are not software.

Re: “C is how the computer works” is a dangerous mindset for C programmers

#155

Earlier quoted context omitted.

I'm intrigued that you make that claim when as far as I know most microcode is proprietary and not necessarily documented. Also that claim is highly dependent on which cpu and manufacturer you're talking about, if the cpu needed to be updated, etc.

The micro-architectures are reasonably documented enough (e.g. we know what each the execution ports do, that register renaming is a thing) and if you look at e.g. Agner Fog's instruction tables [0] that map macro-instructions onto latencies and port counts, that gives a pretty reasonable picture of what's going on. [0] https://www.agner.org/optimize/instruction_tables.pdf

In other words, the assembly code itself isn't really a good picture of what is happening.

Re: “C is how the computer works” is a dangerous mindset for C programmers

#156

"Real hardware" is also an abstract machine. Until you get to the level of each individual transistor, it's hardware abstractions all the way down. Caches, reorder buffers, load and store buffers, instruction decoding are all abstract concepts sitting at a much higher level than the individual transistor. Those abstractions are there mostly for the purpose of speeding up code execution, but also for enabling hardware…

And I bet you physicists argue that transistors are just abstractions of semiconductors

You dont need to go to physics for that, a datasheet on any real transister will tell you that.

Re: “C is how the computer works” is a dangerous mindset for C programmers

#157

Earlier quoted context omitted.

As far as I know (and I could be wrong), reading uninitialized memory in C is not UB, but gives an indeterminate value, which may be either an unspecified value or a trap representation. If it is a trap representation, accessing it is indeed UB, but if all possible values of your memory are valid, e.g. if you have an unpadded integer where every bit representation means something valid, then it is not UB, though it i…

That's the way I think it _should_ work, but sadly does not. For instance, see https://godbolt.org/z/ent-xp

Your code is

    int x;
    if(x == 0) foo();
    if(x != 0) foo();
That is reading the uninitialized value twice. Since it is unspecified, it does not have to be consistent, so you could get the same behavior as non-zero for the first reading, and zero for the second reading. Changing your code to:

    int x;
    if(x == 0) foo();
    else foo();
will give different output (same if you use !=).

Re: “C is how the computer works” is a dangerous mindset for C programmers

#158
post #6

Actually I look forward for enough momentum to be created in the community, to allow new C standards to change the way undefined behaviors are conceived, and make them as specified as possible, and even when they cannot in reasonable unique ways, to provide reference possible behaviors to select in order to have the least unexpected outcome for the programmer. Especially now that low level programming is abstracting…

> allow new C standards to change the way undefined behaviors are conceived, Of all the potential issues that might be attributed to C, undefined behavior (UB) is the one that creates few to no problems at all. To me, complaining about UB is like complaining about the quality of a highway once they intentionally break through the guard rails and start racing through the middle of the woods. The reason why some behavi…

> To me, complaining about UB is like complaining about the quality of a highway once they intentionally break through the guard rails and start racing through the middle of the woods.

Sure, if those guardrails are 1mm tall and so barely visible, then that's a valid analogy to C. I hope you can see why this is not an ergonomic design that will lead to safe programs (or safe highways).

Re: “C is how the computer works” is a dangerous mindset for C programmers

#159

Earlier quoted context omitted.

Okay, you're talking about OoO execution here, and you're right that this can be hard to reason about (in terms of stalls/latencies), however that's orthogonal to microcode translation.

OoO and the fact that CPUs really are free to do whatever transformations they deem fit, as long as the end result within limits of memory model is same.

The CPU must conform to the strictures of the ISA, which is a much more stringent specification than the abstract machines of most language specifications. In particular, the state of registers and flags at any given time need to be preserved, even in the presence of external interrupts.

Note that several decades ago, there were processors that weren't capable of actually keeping the state correct after a processor exception, so if you got a division-by-0 error, your program counter had advanced by 30 or so. (This is, I believe, part of the reason why traps are undefined behavior in C: if your processor can't guarantee any state after a machine trap, it's impossible to implement a programming language that has even the loosest guarantees).

Re: “C is how the computer works” is a dangerous mindset for C programmers

#160
post #152

Earlier quoted context omitted.

As far as I know (and I could be wrong), reading uninitialized memory in C is not UB, but gives an indeterminate value, which may be either an unspecified value or a trap representation. If it is a trap representation, accessing it is indeed UB, but if all possible values of your memory are valid, e.g. if you have an unpadded integer where every bit representation means something valid, then it is not UB, though it i…

Not a C expert, just reading what I can find online: This page says value is indeterminate, which is either unspecified or a trap, as you say: https://wiki.sei.cmu.edu/confluence/display/c/EXP33-C.+Do+no... But. This part says that reading an indeterminate value is, in fact, undefined behavior (line 11 in the table): https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+...

That says used, not read. And indeterminate, not unspecified. My point was on reading a value, not on acting on the value. I know it looks like nit-picking, and you should just not read uninitialized memory, but I don't think it's consistent with the standard to say that reading uninitialized memory is always UB.
Post reply on HN