Live data from Hacker News

Clang vs. Clang

blog.cr.yp.to

251–260 of 405 posts

Re: Clang vs. Clang

#251
post #224

Earlier quoted context omitted.

> but “ridiculous amount” and “difficult to avoid” is overstating it Maybe you can argue that C doesn't have a “ridiculous amount” of UB (even though the number is large), but C++ is so much worse I don't think saying it's “ridiculous” is off the mark. And not only the amount is already ridiculous but every new feature introduced in modern versions of C++ adds its own brand new UB!

If you count the number of UB in the standard, then yes, 200 cases is high. There is some ongoing effort to eliminate many of them. But it should also be noted, that almost all of those cases are not really problematic in practice. The problematic ones are signed overflow, out-of-bounds, use-after-free, and aliasing issues. Signed overflow is IMHO not a problem anymore because of sanitizers. In fact, I believe that u…

> Out-of-bounds and use-after-free can be dealt with by having good coding strategies

You're basically saying that every project in the wild has bad “coding strategy”…

> I expect that we will have full bounds safety options in compilers soon

Which will be disabled in most places because of the overhead it incurs.

> But having a good ownership model and good abstractions also avoids most problems here in my experience. I rarely have actual problems in my projects related to this.

It's easier said than done when you have no way of enforcing the ownership, and practically intractable when not working alone on a codebase.

Re: Clang vs. Clang

#252
post #215

Earlier quoted context omitted.

> Isn't this unreasonable? Here we are, 52, years down the road with C et al. and suddenly it's expected that compiler developers must consider any change in the light of timing attacks? We already went through a similar case to this: when the C++11 multithreaded memory model was introduced, compiler authors were henceforth forced to consider all future optimizations in light of multithreading. Which actually forced…

It is completely unreasonable though to assume that a compiler should now preserve some assumed (!) timing of source operations. It would be reasonable to implement (and later standardize) a pragma or something that specifies timings constraint for a subset of the language. But somebody would need to do the work.

An attribute for functions that says "no optimisations may be applied to the body that would change timings" seems like a reasonable level of granularity here, and if you were conservative about which optimisations it allowed in version zero it'd probably not be a vast amount of work.

I'm sort of reminded of the software people vs. hardware people stuff in embedded work, where ideally you'd have people around who'd crossed over from one to another but (comparing to crypto authors and compiler authors) there's enough of a cultural disconnect between the two groups that it doesn't happen as often as one might prefer.

Re: Clang vs. Clang

#253
post #114
post #100

Earlier quoted context omitted.

To be pedantic, I think you're speaking about unspecified behavior and implementation defined behavior. Undefined behavior specifically refers to things that have no meaningful semantics, so the compiler assumes it never happens. Unspecified behavior is anything outside the scope of observable behavior for which there are two or more ways the implementation can choose. Since the timing of instructions on machines wit…

I am referring to undefined behavior. For example, consider the case integer overflow when adding two signed numbers. C considers this undefined behavior, making the program's behavior is undefined. All bets are off, even if the program never makes use of the resulting value. C compilers are allowed to assume the overflow can never happen, which in some cases allows them to infer that numbers must fit within certain…

Signed integer overflow being undefined has these two consequences for me: 1. It makes my code slightly faster. 2. It makes my code slightly smaller. 3. It makes my code easier to check for correctness, and thus makes it easier to write correct code.

Win, win, win.

Signed integer overflow would be a bug in my code.

As I do not write my own implementations to correctly handle the case of signed integer overflow, the code I am writing will behave in nonsensical ways in the presence of signed integer overflow, regardless of whether or not it is defined. Unless I'm debugging my code or running CI, in which case ubsan is enabled, and the signed overflow instantly traps to point to the problem.

Switching to UB-on-overflow in one of my Julia packages (via `llvmcall`) removed like 5% of branches. I do not want those branches to come back, and I definitely don't want code duplication where I have two copies of that code, one with and one without. The binary code bloat of that package is excessive enough as is.

Re: Clang vs. Clang

#254
post #69

Earlier quoted context omitted.

It’s true that UB is not intuitive at first, but “ridiculous amount” and “difficult to avoid” is overstating it. You have to have a proof-writing mindset when coding, but you do get sensitized to the pitfalls once you read up on what the language constructs actually guarantee (and don’t guarantee), and it’s not that much more difficult than, say, avoiding panics in Rust.

In my experience it is very easy to accidentally introduce iterator invalidation: it starts with calling a callback while iterating, add some layers of indirection, and eventually somebody will add some innocent looking code deep down the call stack which ends up mutating the collection while it's being iterated.

That is not UB. That is simply mutable data. The solution here is static analysis (Rust) or immutable persistent collections.

Re: Clang vs. Clang

#255

Earlier quoted context omitted.

We had ~30 years of "undefined behaviour" practically meaning "do whatever the CPU does". It is not new that people want predictable behaviour, it simply wasn't a talking point as we already had it.

When were those decades? Any decent optimizing compiler built in the last couple of decades exploits undefined behavior.

You pretty much answered your own question. ~20 years ago and back. But I think it is also worth pointing out that it has gotten worse, those 20 years has been a steady trickle of new foot guns.

Re: Clang vs. Clang

#256
post #224

Earlier quoted context omitted.

If you count the number of UB in the standard, then yes, 200 cases is high. There is some ongoing effort to eliminate many of them. But it should also be noted, that almost all of those cases are not really problematic in practice. The problematic ones are signed overflow, out-of-bounds, use-after-free, and aliasing issues. Signed overflow is IMHO not a problem anymore because of sanitizers. In fact, I believe that u…

> Out-of-bounds and use-after-free can be dealt with by having good coding strategies You're basically saying that every project in the wild has bad “coding strategy”… > I expect that we will have full bounds safety options in compilers soon Which will be disabled in most places because of the overhead it incurs. > But having a good ownership model and good abstractions also avoids most problems here in my experience…

No, I am not saying that every project in the wild has a bad "coding strategy". Some of the most reliable software I use everyday is written in C. Some of this I use for decades without every encountering a crash or similar bug. So the meme that "all C code crashes all the time because of UB" is clearly wrong. It is not intractable, in my experience you just have to document some rules and occasionally make sure they are followed. But I agree that a formal system to enforce ownership is desirable.

Re: Clang vs. Clang

#257
post #228

Earlier quoted context omitted.

I do not think there is a reason to fork. Just contribute. I found GCC community very welcoming. But maybe not come in with an "I need to take back the compiler from evil compiler writers" attitude.

From personal experience, they couldn't care less if they can argue it's "undefined". All they do is worship The Holy Standard. They follow the rules blindly without ever thinking whether it makes sense. But maybe not come in with an "I need to take back the compiler from evil compiler writers" attitude. They're the ones who started this hostility in the first place. If even someone like Linus Torvalds can't get them…

This was a very good example for the nonconstructive attitude I was talking about.

Re: Clang vs. Clang

#258

Earlier quoted context omitted.

That was my thought reading this article. If you want to produce machine code that performs operations in constant time regardless of the branch taken, you need to use a language that supports expressing that, which C does not.

Heck, CPUs themselves aren't suitable for constant time operations. At any time, some new CPU can be released which changes how quick some operations are.

It is not a problem that different CPUs have different execution time, the problem is if the same CPU, running the same instruction has a timing difference depending on the data it operates on. In this regard CPUs have actually gotten better, specifically because it is a feature that AMD and Intel has pursued.

Re: Clang vs. Clang

#259
Man attempts to write constant time algorithms using language that does not support constant time algorithms, but who’s really at fault here?

Find out on next weeks episode of “lets blame compilers rather than my choice of language”!

Re: Clang vs. Clang

#260
post #25

Earlier quoted context omitted.

You can’t realistically have a C compiler that doesn’t do any optimizations. For one thing, CPU caches are wonders of technology, but a C compiler that only uses registers for computations but stores all results in memory and issues a load for every read will be unbearingly slow. So, you need a register allocator and if you have that, you either need (A) an algorithm to spill data to memory if you run out of register…

I recommend doing some experiments before considering no register allocation unbearingly slow. I once tried running Gentoo with everything compiled -O0 and the user experience with most software wasn't significantly different. The amount of performance critical C code on a modern PC is surprisingly low. Stuff like media decoding is usually done in assembly.

> I recommend doing some experiments before considering no register allocation unbearingly slow. I once tried running Gentoo with everything compiled -O0

AFAIK, register allocation is one of the few optimization passes which are always enabled on all compilers, even with -O0, so your experiment proves nothing.

Post reply on HN