Live data from Hacker News

The Problem with Friendly C

blog.regehr.org

61–70 of 174 posts

Re: The Problem with Friendly C

#61
Since, according to Chandler Carruth, the aim for Clang is to not do optimizations based on undefined behaviour without a corresponding instrument in ubsan[0], I don't see much traction on this well-defined/boring C effort.

You know, in my experience, things would be great if people actually turned on warnings. I write all my new code with -Weverything with a few noise categories turned off. Everybody should build code at this level from day 1.

[0] http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html

Re: The Problem with Friendly C

#62
post #44
post #13

Earlier quoted context omitted.

What modern interpretation? As long as C has been standardized, undefined behaviour has meant nasal demons. There's an argument to be had that some undefined behaviour should rather be unspecified or implementation-defined, but compilers making use of it for aggressive optimization? That's by design. Quoting another article by John Regehr: My view is that exploiting undefined behavior can sometimes be OK if a good de…

How about being build-system defined? As in, let me specify a "target behavior profile" as a switch to the compiler, which would be shorthand for a bunch of switches that define specific results for specific undefined behaviors: "-foverflow=checked" (add explicit checks) vs. "-foverflow=wrap" (do what most ISAs already do, but even on target ISAs that don't do that) vs. "-foverflow=clip" (do something weird that no t…

GCC has an intermediate representation. It's just not exercised as a separate project (like LLVM). It's far from "single pass"

Re: The Problem with Friendly C

#63

Earlier quoted context omitted.

For example, knowing that INT_MAX+1 is undefined allows optimizing "X+1 > X" to "true". If a programmer writes "X+1 > X", chances are this is an overflow check. Doing this is perfectly defined by the standard if X is an unsigned integer, but not if it's signed. That's what doesn't make sense, since they could've made the unsigned case undefined as well. which allows a broad range of loop optimizations to kick in What…

> I don't believe C should be a language where the compiler does all sorts of high-level optimisation; it should be a straightforward "do what I say" type of language where you get almost exactly what you write, and the only optimisations should be at the level of things like instruction selection --- the optimisations that a programmer would not be able to do at the source level. In that case, you're asking for easi…

IMHO aggressive optimization at compile time is an example of premature optimization. Let the hardware have access to a straightforward representation. Once the run-time hot-spots are identified, the hardware (firmware, VM, whatever) can rewrite the binary code to execute faster. Excessive compiler optimization makes this difficult or impossible (too much information thrown away.) Compilers should be designed for fast compilation speed.

Re: The Problem with Friendly C

#64
post #63

Earlier quoted context omitted.

> I don't believe C should be a language where the compiler does all sorts of high-level optimisation; it should be a straightforward "do what I say" type of language where you get almost exactly what you write, and the only optimisations should be at the level of things like instruction selection --- the optimisations that a programmer would not be able to do at the source level. In that case, you're asking for easi…

IMHO aggressive optimization at compile time is an example of premature optimization. Let the hardware have access to a straightforward representation. Once the run-time hot-spots are identified, the hardware (firmware, VM, whatever) can rewrite the binary code to execute faster. Excessive compiler optimization makes this difficult or impossible (too much information thrown away.) Compilers should be designed for fas…

That would work if most applications spent all their time in a few hot spots. But, contrary to popular wisdom, that's usually not the case. Most applications have flat profiles (to steal a quote from DannyBee—but it matches my experience as well). They have flat profiles because people have spent a lot of time optimizing them. In this context—which is the norm—eliminating optimizations to save compile time and deferring optimization to a few "hot spots" has the effect of turning off optimization for the whole program.

It's common to write off compiler optimizations as unimportant, because they're invisible and people don't see them. They're also complex, which makes people predisposed to get rid of them in the name of "simplicity". But, for better or for worse, optimizing compilers are necessary complexity.

Optimizing compilers are not ubiquitous because compiler engineers just like to play with technology. They're ubiquitous because you need them.

Re: The Problem with Friendly C

#65
post #63

Earlier quoted context omitted.

IMHO aggressive optimization at compile time is an example of premature optimization. Let the hardware have access to a straightforward representation. Once the run-time hot-spots are identified, the hardware (firmware, VM, whatever) can rewrite the binary code to execute faster. Excessive compiler optimization makes this difficult or impossible (too much information thrown away.) Compilers should be designed for fas…

That would work if most applications spent all their time in a few hot spots. But, contrary to popular wisdom, that's usually not the case. Most applications have flat profiles (to steal a quote from DannyBee—but it matches my experience as well). They have flat profiles because people have spent a lot of time optimizing them. In this context—which is the norm—eliminating optimizations to save compile time and deferr…

I agree optimization is important. So important that it should be pushed down into the hardware. Binaries should look almost like source code. But that's just my vision for what it's worth.

Re: The Problem with Friendly C

#66
post #27

Tone: I do not mean this as sarcasm or merely chasing fashion, I'm quite serious. As both theory and practice are showing, you're never going to be able to get the consensus you want out of C. There's no "saving" C... not because that's somehow mathematically impossible, but simply because the project is too staggeringly large for us to even wrap our heads around. It would literally be easier to get people to start u…

Actually I think you are being rather timid in your proposal. C is the symptom: the cause is the underlying Von Neumann machine. The future is hardware - re-configurable hardware connected as needed for the present purpose.

Re: The Problem with Friendly C

#67
Being an ignorant fool with an uninformed opinion, I would like to see a C compiler that is evaluated and critiqued not only based on the warnings and errors it generates but, more importantly, on the assembly it generates.

Namely, how compact and readable is the generated asm? When we read the asm, can we easily follow what the compiler has done and _why_?

As an ignorant fool, in my mind C is still a shorthand for writing assembly, to save old programmers from continuing to be or new programmers from becoming "assembly language programmers". Obviously many years have passed and "C" has become an institution and means much more to so many people. Aopologies to those people. I am just a fool.

I see the _theoretical_ "C compiler" as nothing more than a code generator, spitting out assembly. Obviously the _practical_ C compiler is very different. Base on the way it's used, it seems inextricably linked with a "preprocessor" (glorified sed).

It is said that asm has a "one to one" relationship with machine code. Theoretically, we can look at asm and determine its machine code equivalent without any "clever" algorithms.

My humble, ignorant fool's opinion is that it would be better if C had a closer relationship to the asm the "C compiler" generates.

Maybe not "one to one" but at least "predictable, boring".

Forgive me for having opinions about overly complex things few people can comprehend (e.g., a "modern C compiler"). I am just an ignorant fool who likes code generators. Especially ones that output assembly.

Re: The Problem with Friendly C

#68
You have to choose whether or not you want the compiler to generate code that spends time doing things that the programmer didn't ask for.

If you write a library with a function which accepts variables x and y and computes x[y] (or xmust add some kind of branching logic in there to check what's passed in at runtime. In other words, spend time doing things the programmer didn't ask for.

Maybe when we make more progress with formal proof-generating languages, we can create a "friendly" C where the compiler refuses to compile the code until it's accompanied by formal proofs of UB-avoidance.

Re: The Problem with Friendly C

#69
post #23
post #9

Earlier quoted context omitted.

Probably because it would go in the same direction as multiple-dialects proposal. If we can have bcc-x86 that returns x ans bcc-arm that returns 0, then we'll likely end up with bcc-x86-fullshifting-nounaligned-nullcheckremoveok-otheroptions and 10 dialects that switch some of those behaviours. If you're designing a well-defined language, then why make it well-defined-per-architecture?

But the standard already permits this. I'm just suggesting that rather than have compiler writers use these liberties to allow their compiler to remove code or make it do something peculiar, they could just allow it to do the natural thing for the target platform. (This is explicitly allowed by the standard. Consult its definition of undefined behaviour.) Why not create a compiler that does what your users want? Why…

Because the overwhelming majority of users of C compilers are compiling someone else's code that isn't narrowly targeted to the platform+compiler in question. So they get no benefit at all from specifying undefined behavior, but they do get a benefit from the performance gained by assuming away undefined behavior as dead cases.

Re: The Problem with Friendly C

#70
post #27

Tone: I do not mean this as sarcasm or merely chasing fashion, I'm quite serious. As both theory and practice are showing, you're never going to be able to get the consensus you want out of C. There's no "saving" C... not because that's somehow mathematically impossible, but simply because the project is too staggeringly large for us to even wrap our heads around. It would literally be easier to get people to start u…

I'll take the bet that in 2035 it's still going to be C/C++ (or a C derivative like Boring C). Because rewriting all that code is an economic impossibility. There's a very long way to go before the rate of foundational Rust code written exceeds the rate of foundational C/C++ code written. And even if you manage to have 100% Rust and 0% C/C++ code being written, you still have a huge legacy to write, which literally costs billions of dollars (ALL operating systems, ALL browsers, ALL interpreters (Python/PHP/Perl/...), ALL compilers (GCC, LLVM), ALL web servers, etc.)

Honestly I think your view of technological adoption is fairly naive -- I don't see much content here other than "everyone get behind Rust!".

IMO the more realistic approach is a systems approach: make it so that badly written C code doesn't completely hose your system. I like the application compartmentalization work (Chrome style, DJB style), and capability work like Capsicum. And LangSec work in making safe parsers. The trusted computing base has to be reduced. Not every line of C code should run in a trusted context!!! Principle of least privilege. We know (or should know) all this stuff.

That is many of orders of less magnitude less work / cost, and I think actually feasible. Coherent and secure systems architecture is more achievable than everybody writing perfect C code or everybody switching to another language.

Another thing the Rust community should be working on is easy and efficient IPC with C programs. So you can rewrite a secure core in Rust and communicate with legacy C/C++ running in an untrusted OS context.

And also fixing the mess that is Linux containers, so it isn't so difficult to secure them (i.e. see Docker's security issues)

Post reply on HN