3 ms·
I read this article not as complaining about static checking but as warning that a rule that compilation should not produce any warnings can be counter-producti
by Someone 4y ago
I read this article not as complaining about static checking but as warning that a rule that compilation should not produce any warnings can be counter-productive if many potential problems that get reported are red herrings.
As an extreme example for C, if you had a compiler that issued a warning for every potential int overflow, I think every programmer would ignore those warnings because it would report a warning on such statements as
int foo = bar + 1;
and preventing that requires one to write
int foo;
if(bar != INT_MAX) {
foo = bar + 1;
} else {
???
}
Even ignoring that figuring out what to write for ??? can take a lot of time, that blows up the code. Macros can make the source smaller, but your binary will still be larger and slower.
- nerdponx 4y agoThis is actually my annoyance with monadic error handling. When I'm writing a little command line utility, I don't really want to explicitly handle every edge case. Just let the damn program crash and shame on me.
- piperswe 4y agoAt least with Rust's take on monadic errors, you can sprinkle some `unwrap`s around and get what you want.
- jiggawatts 4y agoIn better languages, the compiler will write that code for you, and eliminate it whenever it can prove that the condition will never be hit. This is one of the philosophical differences between C and other languages that makes everyone consider C unsafe. A legacy language that should no longer be used, because all of its users are perpetually incentivised to take shortcuts precisely like the one you've just described.
- zokier 4y agoMost programming languages are not expressive enough to reliably eliminate redundant overflow checks (or overflows); afaik doing so in general way requires something in the ballpark of refinement/dependent types
- jiggawatts 4y agoIn which case the compiler will emit the overflow or bounds checks, which is fine. If the developer is certain that a specific add operation should use unchecked add for performance, then they can override the behaviour as a spot micro-optimisation. That then becomes a "self documenting" thing, easily found by a simple keyword search. To give you an idea of just how rarely this is actually needed or done, there are less than a thousand uses of "unchecked_add()" in all of the Rust code on GitHub! https://github.com/search?q=.unchecked_add%28+language%3ARust&type=code&l=Rust https://github.com/search?q=.unchecked_add%28+language%3ARus...
- codebje 4y agoIf you don't know what ??? should be, your code's going to misbehave in production - at best crashing, at worst causing data corruption or an exploitable vulnerability. If "???" is just "foo = INT_MIN;" clang will optimise it all down to a single addition (see https://godbolt.org/z/K1ee8h3TM https://godbolt.org/z/K1ee8h3TM). If it's always "foo = INT_MIN;" across all of your code you can just use "-fwrapv" to override the C standard and define signed addition as two's complement wrapping. GCC will ignore the possibility of overflow in signed addition if you don't do anything special (e.g. https://godbolt.org/z/Pc76c5E9z https://godbolt.org/z/Pc76c5E9z). You can use "-ftrapv" (or "-fsanitize-undefined-trap-on-error -fsanitize=signed-integer-overflow") to make bigger, slower, safer code that fails fast on unexpected overflows across the board. You can do the rather unergonomic "__builtin_add_overflow(bar, 1, &foo);" to tell the (GCC or clang, at least) compiler "???" is two's complement wrapping. You can do the cheeky, non-portable, but predictable on the same compiler and platform "int foo = bar + 1L;" to do the same thing. Combine these with "-ftrapv" and you'll get code that short-circuit blows up for unchecked unsigned overflow with the opportunity to produce faster code where you either are damn sure it can't overflow or where you want two's complement wrapping on overflow. If it's not in a tight inner loop avoiding a check is premature optimisation - if you're consuming I/O and doing lightweight processing on it, an overflow flag test on signed additions will not make a measurable performance difference, nor will it blow out your binary size unreasonably. IMO it's not a red herring to have signed integer overflow flagged as a potential error. The error is the failure to have an answer for "???".
- Someone 4y ago> If you don't know what ??? should be, your code's going to misbehave in production Not necessarily. The programmer may know the ??? code will be dead, but it’s not realistic to expect the compiler to deduce that. For example, the programmer may know that, in this program, baz has been checked to be in the range [0,999] ten layers up the call stack, and bar was computed from it five layers up by calling quux, and thus will be in the range [31,98355], which is fine, given that this program tests that int can hold that range at startup. Not all functions in a program have to be free of undefined behavior in isolation to make a program free of it.