5 ms·
Uninitialized memory being UB isn’t an insane default imo (although it makes masked simd hard), nor is most UB. But the lack of escape hatches can be frustratin
by vgatherps 1y ago
Uninitialized memory being UB isn’t an insane default imo (although it makes masked simd hard), nor is most UB. But the lack of escape hatches can be frustrating
- adastra22 1y agoAnything being UB is insane to me...
- IshKebab 1y agoNah it makes some sense for portability between architectures. Or at least it did back when C was invented and there were some wild architectures out there. And it definitely does allow some optimisation. But probably nothing significant on modern out-of-order machines.
- dathinab 1y ago> there were some wild architectures out there. what is out there is still pretty wield just slightly less > probably nothing significant on modern out-of-order machines. having no UB at all will kill a lot of optimizations still relevant today (and won't match anymore to hardware as some UB is on hardware level) out of order machines aren't magically fixing that, just makes some less optimized code work better, but not all and a lot of low energy/cheap hardware does have no or very very limited out of order capabilities so it's still very relevant and likely will stay very relevant for a very long time
- dathinab 1y agoonly until you get deeper into how the hardware actually work (and OS to some degree) and realize sometimes the UB is even in the hardware registers and that the same logical memory address might have 5 different values in hardware at the same time without you having a bug and other fun like that so the insanity is reality not the compiler (through IMHO in C and especially C++ the insanity is how easily you might accidentally run into UB without doing any fancy trickery but just dumb not hot every day code)
- uecker 1y agoI do not find it so easy to accidentally run into UB in C if you follow some basic rules. The exceptions are null pointer dereferences, out-of-bounds accesses for arrays, and signed overflow, all those can be turned into run-time traps. The rules include no pointer arithmetic, no type casts, and having some ownership strategy. None of those is difficult to implement and where exceptions are made, one should treat it carefully similar to using "unsafe" in Rust.
- dooglius 1y agoThere is no UB in hardware registers or physical DRAM, I don't think you actually have familiarity with how the hardware works if you make this claim. (Or perhaps you aren't familiar with how crazy "UB" in the sense of the ISO C documentation is) EDIT: one could see "apparent" violation of memory consistency if say the cache subsystem or memory controller were misconfigured, however this would require both (1) you are running in kernel mode, not user-space (2) you have a bug, so GP's claim is not supported that bug-free code could encounter such a state.
- addaon 1y ago> There is no UB in hardware registers or physical DRAM This seems very sensitive to specific definitions that others might not share. DRAM is provided with a spec sheet that defines its behavior (if you write to an address, you’ll read back the same value from the same address in the future) under certain conditions. If you violate those conditions, the behavior is… undefined. If you operate DRAM with the wrong refresh timing, or temperature, or voltage, or ionizing radiation level, you may see strange behavior. Even non-local behavior, where the value read from one cell depends on other cells (RowHammer). How is this not UB?
- dooglius 1y agoI've edited my claim to be a bit more clear, however in the context of parent's claim we are talking about bug-free code on an non-buggy physical processor, and I think implicitly we are talking about user-mode code where one does not have the ability to alter any DRAM timing configuration registers anyway.
- jcranmer 1y agoHow would you implement integer-to-pointer conversions without UB?
- adastra22 1y agoWhat is UB about integer-to-pointer conversions?
- jcranmer 1y agoPlenty of things! The resulting pointer may not be pointing to an object that is currently live, for example. It may not even be pointing to an object that makes any sense in the language's object model. It might be pointing to a return address on the stack, for example. Or a constant in the constant pool. Or a saved register in the middle of a computation that corresponds to no variables in the original program. In short, the moment you enable integer-to-pointer conversions (assuming your target has a flat address space), you create pointer provenance problems whose only resolution is that some things have to be UB.
- adastra22 1y agoI don't think any of those are undefined behavior in the strict sense in which the term is defined in the C/C++ standards. Pointer casts are defined behavior. I believe the things you point to are either implementation-defined or unspecified, which is different from UB. It may seem nitpicky, but the downside of relying on implementation defined or unspecified behavior is largely boxed and contained. E.g you might get a memory access error. UB is, in principle, completely unlimited in downside. And because of that, it often interacts badly with optimization passes, resulting in very strange bugs.
- pcwalton 1y agojcranmer is correct and pointer provenance-related issues are not "boxed and contained". Start here: https://www.ralfj.de/blog/2020/12/14/provenance.html https://www.ralfj.de/blog/2020/12/14/provenance.html