5 ms·
If you want slow code that behaves exactly the way you expect, turn off optimizations. Congrats, you have the loose assembly wrapper language you always wanted
by nickelpro 2y ago
If you want slow code that behaves exactly the way you expect, turn off optimizations. Congrats, you have the loose assembly wrapper language you always wanted C to be.
For the rest of us, we're going to keep getting every last drop out of performance that we can wring out of the compiler. I do not want my compiler to produce an "obvious" or "reasonable" interpretation of my code, I want it to produce the fastest possible "as if" behavior for what I described within the bounds of the standard.
If I went outside the bounds of the standard, that's my problem, not the compiler's.
- krackers 2y agoJust like -ffast-math, that should be an opt-in flag. I'd bet most people want (and even expect) the compiler to do the sane thing, especially if it only costs them 2% performance. The quest for mythical "performance" over correctness is precisely why we've landed into this situation in the first place.
- nickelpro 2y agoThe compiler does sane things. I also fundamentally disagree with the OP that the situations that invoke UB are surprising. This largely derives from C developers believing they understand the language by thinking of it as a loose wrapper around assembly, instead of an abstract machine with specific rules and requirements. Within the bounds of the abstract machine described by the standard, things like signed integer overflow, pointer aliasing, etc, don't make any sense. They are intuitively undefined. If C developers actually read the standard instead of pretending C describes the 8086 they learned in undergrad, they wouldn't be worried about the compiler doing "sane" things with their unsound code because they wouldn't gravitate towards that code in the first place. No one thinks that dereferencing an integer makes sense, no one accidentally writes that code, because it intuitively doesn't work even in misguided internal models. This doesn't solve problems like buffer overflows of course, which are much more about the logical structure of the program than its language rules. For that style of logical error there's no hope for C in the general case, although static analyzers help.
- RevEng 2y agoThe problem is in how compiler writers have interpreted this as license to do some bizarre things. Does it contain UB? Skip that code entirely without saying a word. Regardless of whether or not the code is malformed, this kind of response is hostile to the user.
- krackers 2y agoIsn't this tautologically saying the compiler does sane things if you define "sane" as what the compiler allows? As Linus said standards are written on toilet paper, in the real world you have a need to do signed overflow and type punning. In the real-world pretty much every system of note uses 2s complement, and if there was a concern about maintaining compatibility with archaic systems it could be made "implementation defined" behavior instead. To get something approximating "sane behavior" you have to set a dozen flags to disable various types of questionable optimizations.
- nickelpro 2y agoNo, C is totally sane for the machine it describes. If you want to describe a different machine, one in which objects can alias, where signed overflow has a specific meaning, etc, you can choose to describe that machine instead using compiler flags. In that case it is on you to understand what new, unstandardized machine you are describing. This is fine and good, nothing wrong with it, and often very useful. The problem is with ever believing what you are describing with C has some 1-to-1 relationship with what the compiler is producing for a given real world hardware implementation. This delusion is unique to C. Fortran, Python, Java, Go, etc, programmers don't ever think about what the underlying hardware is doing with their code. They're writing code for an abstract machine defined by the language in implementation or standard.
- ordu 2y ago> No, C is totally sane for the machine it describes. Are brainfuck[1] or malbolge[2] sane? They do exactly what they says they will do, so following your logic they are sane, aren't they? > The problem is with ever believing what you are describing with C has some 1-to-1 relationship with what the compiler is producing for a given real world hardware implementation. I'm not sure, that it is possible to be a good C programmer and to not have any clue of what the compiler will produce. You need to know, for example, that if you pass something big by value it will lead to copying this value into the stack. You'd better have some idea how many registers compiler uses to pass arguments to functions, and how it uses them to pass structs. Or, as another example, you need to know how C packs structures, so you will not end up with a structure that uses several times more memory than it needs. Besides of this you need to think of cache locality and of other concepts that are not mentioned in the specification of C abstract machine. And these things have much greater impact on the performance then the optimizations that become possible only when compiler allows itself to go crazy with UB. [1] https://en.wikipedia.org/wiki/Brainfuck https://en.wikipedia.org/wiki/Brainfuck [2] https://en.wikipedia.org/wiki/Malbolge https://en.wikipedia.org/wiki/Malbolge
- Filligree 2y agoFor the rest of us, actually we will be using different languages that don't pretend UB is what we want. I'd be using C a lot more if I could possibly trust myself to write correct C.