Because you can't adopt that syntax after the fact. there is 30 years of C++ in the real world, initializing everything by default unless you opt-in will break some performance critical code that should not initialize everything (until it is updated manually - it has to be manual because tools are not smart enough to know where something was intentionally not initialized 100% of the time)
Thus the current erroneous. It means this isn't a bug (compilers used to optimized out code paths where an uninitialized value is read and this did cause real world bugs when it doesn't matter what value is read). It also means the compiler is free to put whatever value they want there - one of the goals was the various sanitizers that check for using uninitialized values need to still work - the vast majority of the time when an uninitialized value is read that is a bug in the code.
There are a lot of situations where a compiler cannot tell if a variable would be used uninitialized, so we can't rely on compiler warnings (it sometimes needs solving the halting problem).
> There are a lot of situations where a compiler cannot tell if a variable would be used uninitialized, so we can't rely on compiler warnings (it sometimes needs solving the halting problem).
It's an explicit choice in C++ to always accept correct programs (the alternative being to always reject incorrect programs†). The committee does not have to stick by this bad decision in each C++ version, of course they aren't likely to stop making the same bad choice, but it is possible to do so.
If you're allowed to take the other side, you can of course (Rust and several other languages do this) reject programs where the compiler isn't satisfied that you definitely always initialize the variable before it's value is needed. Most obviously (but it's pretty annoying, so Rust does not do this) you could insist on the initialization as part of the variable definition in the actual syntax.
† You can't have both, by Rice's Theorem, Henry Rice got his PhD for figuring out how to prove this, last century, long before C++ was conceived. So you must pick, one or the other.
> Because you can't adopt that syntax after the fact.
The `= void` syntax can be because it is currently not valid.
D (unlike C++) always has a default initializer, but does not allow a default constructor. This is sometimes controversial, but it heads off all kinds of problems.
The default initializer for floating point values is NaN. (And for chars it is 0xFF.) The point of this is for the value to not "happen" to work.)
> there is 30 years of C++ in the real world, initializing everything by default unless you opt-in will break some performance critical code that should not initialize everything
...But the change to EB in this case does initialize everything by default?
No it doesn't. It says the value is unspecified but it exists. Sometimes some compilers did initialize everything (this was common in debug builds) before. Some of them will in the future, but most won't do anything difference.
The only difference is some optimizer used to eliminate code paths where they could prove that path would read an uninitialized variable - causing a lot of weird bugs in the real world.
The precise value is not specified, but whatever value is picked also has to be something that isn't tied to the state of the program so some kind of initialization needs to take place.
Furthermore, the proposal explicitly states that (some) variables are initialized by default:
> Default-initialization of an automatic-storage object initializes the object with a fixed value defined by the implementation
> The automatic storage for an automatic variable is always fully initialized, which has potential performance implications.
> The automatic storage for an automatic variable is always fully initialized, which has potential performance implications.
We use floating point operations with deterministic lockstep with a server compiled on GCC in Linux a windows client compiled with MSVC in windows, and an iOS client running on ARM which I believe is compiled with clang.
Works fine.
This is a not a small code base, and no particular care has been taken with the floating point operations used.
I've written a lot of code using that method, and never had any portability issues. You use types with number of bits in them.
Hell, I've slung C structs across the network between 3 CPU architectures. And I didn't even use htons!
Maybe it's not portable to some ancient architecture, but none that I have experienced.
If there is undefined behavior, it's certainly never been a problem either.
And I've seen a lot of talk about TLB shootdown, so I tried to reproduce those problems but even with over 32 threads, mmap was still faster than fread into memory in the tests I ran.
Look, obviously there are use cases for libraries like that, but a lot of the time you just need something simple, and writing some structs to disk can go a long way.
As proven by many languages without native support for plain old goto, it isn't really required when proper structured programming constructs are available, even if it happens to be a goto under the hood, managed by the compiler.
My point is it's bad debating style. 'Everyone knows C is bad for all kinds of reasons ergo, even when someone presents their own actual experience, I can respond with a refrain that sounds good'
Not using goto because you've heard it's always bad is the same kind of thing. Yes it has issues, but that isn't a reason to brush anyone off that have actual valid uses for it.
C allows most of this, whereas C++ doesn't allow pointer aliasing without a compiler flag, tricks and problems.
I agree you can certainly just use bytes of the correct sizes, but often to get the coverage you need for the data structure you end up writing some form of wrapper or fixup code, which is still easier and gives you the control versus most of the protobuf like stuff that introduces a lot of complexity and tons of code.
Check your generated code. Most compilers assume that packed also means unaligned and will generate unaligned load and store sequences, which are large, slow, and may lose whatever atomicity properties they might have had.
Modern versions of standard C aren't very portable either, unless you plan to stick to the original version of K&R C you have to pick and choose which implementations you plan to support.
I disagree. Modern C with C17 and C23 make this less of an issue. Sure, some vendors suck and some people take shortcuts with embedded systems, but the standard is there and adopted by GCC, Clang and even MSVC has shaped up a bit.
Well, if that is the standard for portability then may_alias might as well be standard. GCC and Clang support it and MSVC doesn't implement the affected optimization as far as I can find.
Within the context of this discussion portability was mentioned as key feature of the standard. If C23 adoption is as limited as the, possibly outdated, tables on cppreference and your comments about gcc, clang and msvc suggest then the functionality provided by the gcc attribute would be more portable than C23 conformant code. You could call it a de facto standard, as opposed to C23 which is a standard in the sense someone said so.
That seems highly unlikely. Let's assume that all compilers use the exact same padding in C structs, that all architectures use the same alignment, and that endianness is made up, that types are the same size across 64 and 32 bit platforms, and also pretend that pointers inside a struct will work fine when sent across the network; the question remains still: Why? Is THIS your bottleneck? Will a couple memcpy() operations that are likely no-op if your structs happen to line up kill your perf?
I guess to not have to set up protobuf or asn1. Those preconditions of both platforms using the same padding and endianness aren't that hard to satisfy if you own it all.
But do you really have such a complex struct where everything inside is fixed-size? I wouldn't be surprised if it happens, but this isn't so general-purpose like the article suggests.
No defined binary encoding, no guarantee about concurrent modifications, performance trade-offs (mmap is NOT always faster than sequential reads!) and more.
C has had fixed size int types since C99. And you've always been able to define struct layouts with perfect precision (struct padding is well defined and deterministic, and you can always use __attribute__(packed) and bit fields for manual padding).
Endianness might kill your portability in theory. but in practice, nobody uses big endian anymore. Unless you're shipping software for an IBM mainframe, little endian is portable.
You just define the structures in terms of some e.g. uint32_le etc types for which you provide conversion functions to native endianness. On a little endian platform the conversion is a no-op.
It can be made to work (as you point out), and the core idea is great, but the implementation is terrible. You have to stop and think about struct layout rules rather than declaring your intent and having the compiler check for errors. As usual C is a giant pile of exquisitely crafted footguns.
A "sane" version of the feature would provide for marking a struct as intended for ser/des at which point you'd be required to spell out every last alignment, endianness, and bit width detail. (You'd still have to remember to mark any structs used in conjunction with mmap but C wouldn't be any fun if it was safe.)
I don't think it's faster than a windows game running Vulkan, though, is it? Like, if you benchmarked a game that has native DX12 and Vulkan modes (such as Wolfenstein: The New Colossus, I believe), it will probably have higher FPS in Vulkan mode, right?
Well our game runs faster in DX12 under Proton than Vulkan under Proton.
Of course since Proton uses Vulkan to implement DX12, it means that our Vulkan implementation is simply worse than the one that Valve created to emulate DX12.
I'm sure it's possible to improve that, but it implies that there way to get the best performance out of Vulkan is less obvious than the way to get it out of DX12.
God Roko's Basilisk is the most boring AI risk to catch the public consciousness. It's just Pascal's wager all over again, with the exact same rebuttal.
The culture that brought you "speedrunning computer science with JavaScript" and "speedrunning exploitative, extractive capitalism" is back with their new banger "speedrunning philosophy". Nuke it from orbit; save humanity.
I have never liked the word "manager" because it's rarely useful in practice, the best managers are actually doers who can cut through the performative transparency and "DDoS attack" of constant updates to see when communication is being used to manipulate or mask failure rather than report progress, because the last thing you want is for your employees to become politicians
It's quite interesting to me the way that different "programming cultures" exist around debuggers.
If you grew up doing windows C++ development, looking at things in a debugger is your first step. You only resort to printing values if you can't immediately see what happened in the debugger.
A lot of other envioronment/language cultures are the opposite. Obviously both have their place, but I do feel like more people should use the debugger as the first step instead of the last.
For embedded applications, especially robotics, it tends not to be a great default because it stops the process, which tends to be bad for realtime control loops. That said, a complete hang is the situation where I absolutely would try to get a debugger attached and get a backtrace as one of the first things to try.
The difference I see between a company dealing with this as opposed to an open source community dealing with this is that the company can fire employees as a reactive punishment. Drive-by open source contributions cost very little to lob over and can come from a wide variety of people you don't have much leverage over, so maintainers end up making these specific policies to prevent them from having to react to the thousandth person who used "The AI did it" as an excuse.
When you shout "use AI or else!" from a megaphone, don't expect everyone to interpret it perfectly. Especially when you didn't actually understand what you were saying in the first place.
>I neither tell people to use AI, nor tell them not to use it, and in practice people have not been using AI much for whatever that is worth.
I find this bit confusing. Do you provide enterprise contracts for AI tools? Or do you let employees use their personal accounts with company data? It seems all companies have to be managing this somehow at this point.
Shouldn't this go without saying though? At some point someone has to review the code and they see a human name as the sender of the PR. If that person sees the work is bad, isn't it just completely unambiguous that the person whose name is on the PR is responsible for that? If someone responded "but this is AI generated" I would feel justified just responding "it doesn't matter" and passing the review back again.
And the rest (what's in the LLVM policy) should also fall out pretty naturally from this? If someone sends me code for review, and have the feeling they haven't read it themselves, I'll say "I'm not reviewing this and I won't review any more of your PRs unless you promise you reviewed them yourself first".
The fact that people seem to need to establish these things as an explicit policy is a little concerning to me. (Not that it's a bad idea at all. Just worried that there was a need).
You would think it's common sense but I've received PRs that the author didn't understand and when questioned told me that the AI knows more about X than they do so they trust its judgement.
A terrifying number of people seem to think that the damn thing is magic and infallible.
One of the reasons I left a senior management position at my previous 500-person shop was that this was being done, but not even accurately. Copilot usage via the IDE wasn't being tracked; just the various other usage paths.
It doesn't take long for shitty small companies to copy the shitty policies and procedures of successful big companies. It seems even intelligent executives can't get correlation and causation right.
Some people who just want to polish their resume will feed any questions/feedback back into the AI that generated their slop. That goes back and forth a few times until the reviewing side learns that the code authors have no idea what they're doing. An LLM can easily pretend to "stand behind its work" if you tell it to.
A company can just fire someone who doesn't know what they're doing, or at least take some kind of measure against their efforts. On a public project, these people can be a death by a thousand cuts.
The best example of this is the automated "CVE" reports you find on bug bounty websites these days.
What good does it really do me if they "stand behind their work"? Does that save me any time drudging through the code? No, it just gives me a script for reprimanding. I don't want to reprimand. I want to review code that was given to me in good faith.
At work once I had to review some code that, in the same file, declared a "FooBar" struct and a "BarFoo" struct, both with identical field names/types, and complete with boilerplate to convert between them. This split served no purpose whatsoever, it was probably just the result of telling an agent to iterate until the code compiled then shipping it off without actually reading what it had done. Yelling at them that they should "stand behind their work" doesn't give me back the time I lost trying to figure out why on earth the code was written this way. It just makes me into an asshole.
It adds accountability, which is unfortunately something that ends up lacking in practice.
If you write bad code that creates a bug, I expect you to own it when possible. If you can't and the root cause is bad code, then we probably need to have a chat about that.
Of course the goal isn't to be a jerk. Lots of normal bugs make it through in reality. But if the root cause is true negligence, then there's a problem there.
If you asked Claude to review the code it would probably have pointed out the duplication pretty quickly. And I think this is the thing - if we are going to manage programmers who are using LLM's to write code, and have to do reviews for their code, reviewers aren't going to be able to do it for much longer without resorting to LLM assistance themselves to get the job done.
It's not going to be enough to say - "I don't use LLM's".
Yelling at incompetent or lazy co-workers isn't your responsibility, it's your manager's. Escalate the issue and let them be the asshole. And if they don't handle it, well it's time to look for a new job.
> At my company I just tell people “You have to stand behind your work”
Since when has that not been the bare minimum. Even before AI existed, and even if you did not work in programming at all, you sort of have to do that as a bare minimum. Even if you use a toaster and your company guidelines suggest you toast every sandwich for 20 seconds, if following every step as per training results in a lump of charcoal for bread, you can’t serve it up to the customer. At the end of the day, you make the sandwich, you’re responsible for making it correctly.
Using AI as a scapegoat for sloppy and lazy work needs to be unacceptable.
Of course it’s the minimum standard, and it’s obvious if you view AI as a tool that a human uses.
But some people view it as a seperate entity that writes code for you. And if you view AI like that, then “The AI did it” becomes an excuse that they use.
Bad example. If the toaster carbonized bread in 20 seconds it's defective, likely unsafe, possibly violates physics, certainly above the pay grade of a sandwich-pusher.
Taking responsibility for outcomes is a powerful paradigm but I refuse to be held responsible for things that are genuinely beyond my power to change.
> If the toaster carbonized bread in 20 seconds it's defective, likely unsafe, possibly violates physics, certainly above the pay grade of a sandwich-pusher.
If the toaster is defective, not using it, identifying how to use it if it’s still usable or getting it replaced by reporting it as defective are all well within the pay grade of a sandwich pusher as well as part of their responsibilities.
And you’re still responsible for the sandwich. You can’t throw up your arms and say “the toaster did it”. And that’s where it’s not tangential to the AI discussion.
Toaster malfunctioning is beyond your control, but whether you serve up the burnt sandwich is absolutely within your control, which you will be and should be held responsible for.
That's exactly what I said and at odds with your last comment. You take responsibility for making the sandwich if possible. If not, you're not responsible for the sandwich, but for refunding the customer or offering them something else.
If I'm required to write code using AI without being given time to verify it, then it's also not fair for me to be held responsible for the quality. Agency matters. I will not take responsibility for things that I'm not given the power to address. Of course if I choose to write code with an AI and it comes out badly, that's within my responsibilities.
It's a bad example because typically "whether to toast the sandwich" depends on customer preference (imposed externally) but "whether to use AI" is still mostly up to the worker.
No it’s not. If you burn a sandwich, you make new sandwich. Sandwiches don’t abide by the laws of physics. If you call a physicist and tell them you burnt your sandwich, they won’t care.
I think it depends on the pay. You pay below the living wage? Better live with your sla.. ah employees.. serving charcoal. You pay them well above the living wage? Now we start to get into they should care-territory.
But "AI did it" is not immediate you are out thing? If you cannot explain why something is made the way you committed to git, we can just replace you with AI right?
reply