I actually like unreachable() a lot. What it does is that it invokes undefined behavior, that's all. It does nothing trickier than any other kind of UB. In fact, I could implement unreachable() like this: void unreachable() { (char *)0 = 1; }. Standardizing it however gives interesting options for compilers and tool writers. The best use I can find is to bound the values of the argument of a function. For example, if…
Respectfully, you would already be doing this in any C codebase, with `assert()`, right? We are all checking our preconditions with assert... right?
Catch-23: The New C Standard Sets the World on Fire
161–170 of 275 posts
Re: Catch-23: The New C Standard Sets the World on Fire
#162Earlier quoted context omitted.
> Why would you want that? To aid with optimisation, it basically lets you ask the compiler to remove branches, and provide constraints to the same. An implementation might trap in debug code, but given no context would be provided you'd likely avoid this and would instead use your own wrapper macro to output a message of some sort in that case.
But this example isn't adding a constraint. The if statement is getting optimised away???
The branch containing the unreachable() obviously gets removed but the compiler then propagates the constraint (the condition for that illegal branch), and can prune any other path where `argc <= 2` upstream and downstream, as they are dead code per the constraint.
Re: Catch-23: The New C Standard Sets the World on Fire
#163Earlier quoted context omitted.
Those things aren’t up to the language, they’re up to hardware. C is a portable language that runs on many different platforms. Some platforms might have protected memory and trap on out of bounds memory access. Other platforms have a single, flat address space where out of bounds memory access is not an error, it just reads whatever is there since your program has full access to all memory. The same goes for integer…
The problem is that here is a vicious circle. Most old computer architectures had a much more complete set of hardware exceptions, including cases like integer overflow or out-of-bounds access. In modern superscalar pipelined CPUs, implementing all the desirable hardware exceptions without reducing the performance remains possible (through speculative execution), but it is more expensive than in simple CPUs. Because…
Re: Catch-23: The New C Standard Sets the World on Fire
#164> C23 furthermore gives the compiler license to use an unreachable annotation on one code path to justify removing, without notice or warning, an entirely different code path that is not marked unreachable: see the discussion of puts() in Example 1 on page 316 of N3054.9 I don't agree with that description at all. Here's the code: 1 if (argc The only code path that's "entirely different" is lines 1,4,5 and in that ca…
Re: Catch-23: The New C Standard Sets the World on Fire
#165C is a very large language masquerading as a small language.
Re: Catch-23: The New C Standard Sets the World on Fire
#166C reached its zenith in C90, and saw a few good ideas in C99. Everything since has been wankery from people who either are bored, or have a severe case of C++-envy.
Re: Catch-23: The New C Standard Sets the World on Fire
#167Earlier quoted context omitted.
This is not about code that's found to be unreachable through static analysis (where compilers might warn), but about a manual programmer annotation that claims the code is dynamically unreachable even though statically it might look otherwise.
Why would you want that? Is it to aid building for multiple targets? For debug builds?
Re: Catch-23: The New C Standard Sets the World on Fire
#168> C23 furthermore gives the compiler license to use an unreachable annotation on one code path to justify removing, without notice or warning, an entirely different code path that is not marked unreachable: see the discussion of puts() in Example 1 on page 316 of N3054.9 I don't agree with that description at all. Here's the code: 1 if (argc The only code path that's "entirely different" is lines 1,4,5 and in that ca…
This reminds me of a point made by the late Stan Kelly-Bootle, who for years wrote the Devil's Advocate column in UNIX Review magazine. In the early 1990s, he was discussing Microsoft's new C compiler and noted that in the promo material for the new compiler, it showed a benchmark for a loop that counted from 1 to 10,000 then printed "Hello". MS claimed that without optimization it took a few milliseconds, after opti…
Re: Catch-23: The New C Standard Sets the World on Fire
#169Earlier quoted context omitted.
> many things that are UB in C/C++ are UB because they are really hard to verify at compile time which makes them almost impossible to program around The second half of the sentence doesn't follow from the first. Take everyone's favorite example, signed integer overflow: all you have to do to avoid UB on signed integer overflow is check for overflow before doing the operation (and C23 finally adds features to do that…
My complaint here is that it took C more than 30 years between defining signed integer overflow as UB and providing programmers with standard library facilities to check if a signed integer operation would result in overflow. I much prefer Rust's approach to arithmetic, where overflow with plain arithmetic operators is defined as a bug, and panics on debug-enabled builds, plus special operations in the standard libra…
That's an odd complaint. Rust didn't spring forth fully formed from the ether, it stands on the shoulders of C (and other giants of PL history). 30 years ago you couldn't use Rust at all because it didn't exist.
The reason the committee doesn't just radically change C in all these nice ways to catch up to Rust is because it would be incompatible. Then you wouldn't have fixed C, you'd just have two languages: "old C", which all of the existing C code in the world is written in, and "new C", which nothing is written in. At that point why not just start over from scratch, like they did with Rust?
Re: Catch-23: The New C Standard Sets the World on Fire
#170> Pointers to free'd memory are akin to uninitialized pointers, so free(p) followed by if (p==q) is an instrument of arson What's the reason for this?
Using a freed pointer is incorrect behavior, a bug in shorter terms. If you do anything with a freed pointer (other than assigning new memory), you're inviting all kinds of bugs (independent of what the compiler might be doing with your code).