from the ancient-hardware-backwards-compatibility dept.
ACM Queue magazine has an article with the title "Catch-23: The New C Standard Sets the World on Fire". This article offers opinions and analysis of a new major revision of the C language standard, C23, expected to be voted on in 2023:
[...] Like the previous major revision, C11, the latest standard introduces several useful features. The most important, if not the most exciting, make it easier to write safe, correct, and secure code. For example, the new header standardizes checked integer arithmetic.
[...] C23 also adds new features to protect secrets from prying eyes and programmers from themselves. The new memset_explicit() function is for erasing sensitive in-memory data; unlike ordinary memset, it is intended to prevent optimizations from eliding the erasure.
[...] In addition to these new correctness and safety aids, C23 provides many new conveniences: Constants true, false, and nullptr are now language keywords; mercifully, they mean what you expect. The new typeof feature makes it easier to harmonize variable declarations. The preprocessor can now #embed arbitrary binary data in source files. Zero-initializing stack-allocated structures and variable-length arrays is a snap with the new standard "={}" syntax.
[...] Sadly, good news isn't the only news about C23. The new standard's nonfeatures, misfeatures, and defeatures are sufficiently numerous and severe that programmers should not "upgrade" without carefully weighing risks against benefits. Older standards such as C99 and C11 weren't perfect, but detailed analysis will sometimes conclude that they are preferable to C23.
[...] Developers should also note that C23 has drifted further from C++ than the earlier C standards. The notion that C is (mostly) a subset of C++ is further from reality than ever before.
Magazine article:
Terence Kelly and Yekai Pan. 2023. Catch-23: The New C Standard Sets the World on Fire. Queue 21, 1, Pages 30 (January/February 2023), 19 pages. https://doi.org/10.1145/3588242
(Score: 3, Funny) by khallow on Monday April 03, @11:17AM
Egads! I hope not. That's where I keep all my stuff!
(Score: 4, Insightful) by VLM on Monday April 03, @12:14PM (3 children)
Note that it took, IIRC, NINE YEARS for C11 support to arrive in visual studio vs a couple months in GCC, so you might not get portable-ish code using C23 until the 2030s.
It'll be awhile...
(Score: 4, Insightful) by EJ on Monday April 03, @03:28PM
That's ok, because Microsoft isn't going to let us run our own code on Windows 12 anyway. They will provide access to all the applications we "need" on a subscription basis.
"Writing your own applications is for criminals who use Linux." -- Microsoft Rep.
(Score: 2) by turgid on Monday April 03, @04:43PM (1 child)
I thought GCC could target Windows?
I refuse to engage in a battle of wits with an unarmed opponent [wikipedia.org].
(Score: 3, Touché) by DannyB on Monday April 03, @06:03PM
The word "target" could have multiple possible meanings in that sentence.
Ballmer: 'Linux is a cancer' [theregister.com]
How often should I have my memory checked? I used to know but...
(Score: 2) by tekk on Monday April 03, @04:48PM (13 children)
Given that UB is the definition of a footgun, it's really disappointing to see C23 expanding its definition to include something which was previously defined and used for decades. I guess they have to include something broken in every feature release.
(Score: 3, Insightful) by DannyB on Monday April 03, @06:04PM
Don't blame them. It is mandated in their charter.
How often should I have my memory checked? I used to know but...
(Score: 2) by turgid on Monday April 03, @07:25PM (8 children)
What is UB?
I refuse to engage in a battle of wits with an unarmed opponent [wikipedia.org].
(Score: 2) by tekk on Monday April 03, @08:37PM (7 children)
Undefined Behavior, arguably the biggest problem with C. In C many operations which are easy to accidentally perform are defined as "undefined behavior" meaning that there are no rules governing what it does and compilers are allowed to assume that this will never happen when performing optimizations. A famous example goes like this:
I define a static (only visible from the current .c file) function pointer, foo, to be = NULL
In function bar, I set foo to = baz, a function which crashes the system, say a fork bomb.
my main is as follows:
foo();
Because calling a function pointer which is NULL is undefined behavior, the compiler assumes that foo MUST = baz, even though bar was never called, and executes the fork bomb. This was actually the case for clang a few years ago: https://kristerw.blogspot.com/2017/09/why-undefined-behavior-may-call-never.html [blogspot.com]
(Score: 2) by turgid on Monday April 03, @09:08PM (5 children)
That's a compiler bug! The compiler writer assumed that a particular C++ optimisation was relevant for C and that it should apply at all times. "Undefined Behaviour" in the language shouldn't mean "feel free to do a load of crazy stuff that you happen to feel like today just because you can." I reckon that the compiler should cause the program to abort in such cases wherever possible. Or use a better language.
I refuse to engage in a battle of wits with an unarmed opponent [wikipedia.org].
(Score: 3, Insightful) by tekk on Tuesday April 04, @12:32AM (4 children)
Unfortunately ever since the concept was introduced the writers of compilers have taken "undefined behavior" to mean "Feel free to do a load of crazy stuff that you happen to feel like today just because you can". Because the compiler is free to assume that undefined behavior never occurs, anything goes when it comes to its treatment when it shows up. Luckily UB would never be defined in such common cases as signed integer overflow, null pointer dereferences, out of bounds array accesses, etc ;)
(Score: 2) by coolgopher on Tuesday April 04, @01:44AM
For cases declared to be UB, it's perfectly standard compliant for the compiler to emit code that sets the world on fire.
(Score: 3, Interesting) by driverless on Tuesday April 04, @02:34AM (2 children)
Yup. An extreme example of this is gcc, where the devs take a perverse pride in having the compiler break things just to show off how much cleverererer they are than you. For example everything that gcc generates code for is twos-complement but the spec says you don't have to assume that and so gcc doesn't (and kludges like -fwrapv and so on don't fix it, the compiler still breaks code).
This is why there's a huge market for expensive embedded-systems compilers, you can never use gcc on any kind of critical system because you have no idea what it'll end up doing to your code. The devs at Keil, IAR, and so on are motivated to produce safe, reliable code that works as expected. The devs of gcc seem to be motivated to show off how clever they are by breaking code so it doesn't work as expected, but you typically won't notice until it's been in production for several years.
Having said that, I'm a bit on the fence over this since gcc braindamage has earned me several overseas trips, including three weeks in France, while fixing up compiler breakage for customers.
(Score: 3, Funny) by driverless on Tuesday April 04, @02:40AM (1 child)
Ah, hit Submit too soon: I can just see the gcc devs rubbing their hands over the opportunities presented by C23, looking forward to how much existing code they can break to, once again, prove how much cleverer they are than you.
(Score: 4, Funny) by tekk on Tuesday April 04, @05:09AM
Ah, that explains it actually: -O3 was getting stable enough that people were using it, so they had to help out with the new spec!
(Score: 1, Insightful) by Anonymous Coward on Monday April 03, @11:36PM
Fascinating. Just for grin and giggles I tried it with the old MSVC compiler I use (the latest version may be different). It doesn't produce a warning like I'd expect; but if I typedef the function to take an int and supply a float when calling it, it dutifully warns me about the implicit conversion and possible loss of data. Not sure who to be mad at here. Compiler authors? The standard? Maybe both. There's nothing that says your compiler can't warn about stuff like that, and it most assuredly should.
(Score: 2) by dwilson on Monday April 03, @07:38PM (1 child)
I don't do a lot of C programming, and definitely don't do it for a living, so my opinion isn't worth much on this.
That being said, my thinking runs something like this: if I've got C code that has compiled and run fine for decades and now the compiler flags it as an error, then perhaps there were edge cases where it would not have compiled and run fine, which means the code is not the 'good code' I thought it was, and I need to re-think and re-write instead of deciding that 'they' are breaking things.
Would my opinion change if I had to maintain multiple codebases, with millions of lines of code to worry about? Probably. Almost certainly. But I don't.
What I do have to maintain is a single small desktop application originally written in in the early 00's. I forked it around the time GCC7 was the latest stable release, and I took the time to clean up the codebase, used -wall and fixed every single compile-time warning it threw at me. Updated to the latest releases of the libraries being linked, too (the older versions being used had reached EOL and were being dropped from distribution repo's, which is why I originally got involved at all).
Something changed when GCC10 was released and it stopped compiling, throwing new errors. I grumbled a bit but I fixed them. Something changed when GCC11 was released, and it stopped compiling. I spent some time swearing but fixed those too.
The codebase didn't change. The code that previously complied and ran fine just... stopped compiling. I don't write compilers. I don't want to be involved at that level. If previously-working code stops working due to the compiler enforcing newer language standards, I will cheerfully assume that the previously working code had the potential to cause UB, and will be better off re-written.
That's an easy position to take when all it costs is a few evenings of my time. I'm glad I don't write C for a living.
- D
(Score: 2) by tekk on Monday April 03, @09:02PM
The behavior was previously defined by the C standard, though. From C17:
If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size.
Otherwise, if ptr does not match a pointer earlier returned by a memory management function, or if
the space has been deallocated by a call to the free or realloc function, the behavior is undefined.
If size is nonzero and memory for the new object is not allocated, the old object is not deallocated.
If size is zero and memory for the new object is not allocated, it is implementation-defined whether
the old object is deallocated. If the old object is not deallocated, its value shall be unchanged.
(https://web.archive.org/web/20181230041359if_/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf)
So the malloc behavior was explicitly enshrined in the spec, and the free behavior was implementation-dependent and crucially, would never clobber the pointer (returning NULL so that you know that this realloc doesn't implement this and letting you call free.)
They've taken previously well-defined behavior and declared it undefined.
(Score: 2) by driverless on Tuesday April 04, @01:01AM
Yup, and most of the rest of it has degenerated to the UI-refresh stage, pointless breaking change for the sake of change. We've had a memset_explicit() for years as memset_s(), the safe-add macros that almost everyone ignores because they're a massive pain to deal with have been with us for ages when what the C standard needs is a safe_int (vs. the standard int) and the compiler, not the programmer, takes care of it for you because that's what it's there for, zero-initialisation has been around for years with '{ 0 }', etc. Overall C23 brings (a) a pile of UI-refresh wank that no-one needs and (b) lots of breakage.
(Score: 5, Interesting) by turgid on Monday April 03, @07:21PM (1 child)
C++ hasn't been a superset of C for a very long time. When I really started to learn C++ properly, I really got to understand this. In those days it was C++98. I was working on a code base of about 250k lines which had mostly been written in C (badly, in a hurry and a panic by a team of people thrown at a problem long past its deadline).
Subsequently the team had tried to get the code under control (under automated test and so on) and had started to add new layers on top in C++. They were very strict about coding standards and had static analysis that had to pass before any code to be integrated. That was a great way to learn quickly about a lot of nuances, and it really showed up the differences between C and C++.
As part of this exercise, the decision was taken that some of the C code should also compile with the C++ compiler, to get the benefit of stricter type checking but it also had to compile as valid C for other non-C++ compilers. You can see where this is going... Anyway, some C code will compile in a C++ compiler with warnings. You can add explicit typecasts to the C to make a lot of the problems go away but there are a few semantic differences when the code is compiled under the different compilers that can catch you out and therefore you must avoid when programming in either. I used to know what these were but it's a long time ago.
That's when I began to develop my distaste for C++. It's also when I realised that you should use the right compiler for the right language. If you are going to put your C code through a C++ compiler and expect sensible results, to need to convert your C++ code to C. Don't try to pretend that they are the same language. They are not. You will have all sorts of subtle problems that you probably won't notice at first.
C++ zealots will tell you that you should convert your C code to C++ anyway because C++ is "just better." That may be the case in some situations, and if you can justify it, go right ahead but understand the testing and debugging effort involved. Any changes to code imply a test/debug cycle.
However, the is no law natural or artificial which says you can't keep your C code as C and compile it with a proper C compiler and keep your C++ as C++ and compile it with a C++ compiler. You can call your C code from C++ (extern "C") and you can even contrive to export a plain C API and ABI from your C++ code and call it from C (it's more work but it can be done).
Don't pretend that C is just C++ without the fancy bits. They're different languages. They diverged when C++ ceased to be a pre-processor for C.
I refuse to engage in a battle of wits with an unarmed opponent [wikipedia.org].
(Score: 3, Insightful) by coolgopher on Tuesday April 04, @01:47AM
Indeed. It's not uncommon for us at $work to have binares which comprises both C and C++ files, each compiled with the correct compiler. Use the right tool for the right job.
(Score: 4, Insightful) by istartedi on Monday April 03, @11:54PM
After reading TFA about realloc, that alone is reason enough to boycott C-23. Frankly, I'm not even aware of anything I'd want with C11. When inttypes.h got standardized in C99 that was nice even though I was already #ifdef'ing for platforms that had something like that and defining my own if they didn't. IIRC, they added complex arithmetic then but it seems like most people who do that kind of math would have rolled their own or would use a library. C99 really seemed like the Netscape Navigator 3.x of C standards to me, and they were close to the same era too. C-23 sounds like Netscape Communicator, and the standards committee seems like AOL.
Appended to the end of comments you post. Max: 120 chars.
(Score: 2) by Mojibake Tengu on Wednesday April 05, @05:31AM (1 child)
I expect some inevitable catastrophe in C world happening at standard level C23.
Number 23 is sacred in both paradigms of Discordian Magic and Chaos Magic.
For the first, in Discordian paradigm he who ignores Goddess Eris will suffer twice as much effect from her since Eris really hates to be ignored.
This could be avoided only with proper dedication of C Standard to Eris but Kassandra's prediction is those ignorant commissioners will not perform that properly or at all.
For the second, The Zothyrian Abyss Cthulhu spawns are even more unpredictable:
https://en.wikipedia.org/wiki/23_enigma#Origins [wikipedia.org]
Please consult Fortean Society experts for more insight to this dangerous situation.
The edge of 太玄 cannot be defined, for it is beyond every aspect of design
(Score: 2, Disagree) by bart9h on Wednesday April 05, @09:16PM
Yeah, we should consult the Fortran experts.