> Imagine this code...In a world where you can't optimize based on UB assumptions, x can change in the body of f.

Yeah, so you allocate space on the stack (which is free, by the way, because space has to be allocated anyway for the new function's frame), store to it, and load from it.

An extra store and an extra load. Of stack space that was probably already in cache anyway.

So what? What a miniscule price to pay. [0]

> You don't need to share memory across threads to opt in to data races. You can access whatever you want with pointer arithmetic if you want to be correct in the presence of UB.

So C should have bounds checks and define a failing bounds check as an abort. And then such optimizations could be correct. That's what so many other languages do, and it works.

> Or this code...f could be deleted. This could be UB.

Do you mean freed?

Yes, that could be UB. But the compiler should never say, "Oh, well, f could be freed here, so I'm just going to delete the `f->do()` call."

Bad example because compilers don't currently take advantage of it. They day they take advantage of that is the day that I quit programming.

> I do not believe this. I am one of the people at my company fighting to spend performance to buy safety.

Ha! I do not believe you at all! You are okay with compilers taking advantage of UB to elide a store and a load.

The only way you are telling the truth is if your company is full of malicious compiler authors.

> I just don't believe that the principle of least surprise can be implemented in the standard in the way some people say

It totally could. C could even have bounds checks without changing the ABI. They just don't.

> I don't believe that UB is totally unique from other forms of incorrectness in a way that should cause us to behave very differently about it.

It's the only form of incorrectness that:

* Will destroy everything.

* That compiler authors claim they have a right to take advantage of.

Yeah, we definitely should treat it differently. You are dead wrong.

> Do you run your production binaries with all of the sanitizers enabled?

No, because I don't work in the industry.

But in my personal code, I wrote my own bounds checks and enabled them. In C. In release mode. All your talk of "but you could make a pointer to anywhere" doesn't happen in my code.

I use structured concurrency to allocate and free items in only one place, in the same stack frame. When threads are created, they prevent the creating thread from returning from the stack frames that the children may have gotten pointers to.

I fuzz like you wouldn't believe and make sure all paths come back clean in ASan, UBSan, TSan, and Valgrind, including memory leaks.

I add all unique paths from fuzzing to my test suite.

I'm going to write my own malloc() that will have double-free and use-after-free checks.

I use unsigned types to avoid signed overflow, and such unsigned types more easily trip the bounds checks when they overflow because the bounds checks only need one condition.

Tell you what: I would like you to take version 6.7.2 of my bc [1] and get it to execute UB. Any UB is fine.

If you do, I'll enable sanitizers on my release builds of all of my software.

But you won't, and that's why I can forego sanitizers on release builds: I do enough work to ensure that UB won't happen.

And that's why I use unsigned types. Your bellyaching about their poor optimization will not change that.

[0]: https://gavinhoward.com/2023/10/he-who-gives-up-correctness-...

[1]: https://git.gavinhoward.com/gavin/bc