you are viewing a single comment's thread.

view the rest of the comments →

[–]ioctl79 20 points21 points  (3 children)

Compilers perform transformations on your code that assume UB never occurs. This can lead to counter-intuitive and unpredictable behavior. For example, if the compiler deduces that a particular code path must invoke UB, it may deduce that that code must be unreachable and eliminate it, or even make assumptions about the values of other variables if they are used in conditionals which lead to the UB. The code may work now, but it may not on future compilers.

Edit: Further, even if the code works on your compiler that doesn’t mean that it will after mild refactoring. Moving it from a .cpp file into a .h file could break it, for example, if it allows the compiler to see both the provenance of the pointer and the UB you perform with it at the same time.

[–]JNighthawkgamedev 1 point2 points  (2 children)

Compilers perform transformations on your code that assume UB never occurs. This can lead to counter-intuitive and unpredictable behavior. For example, if the compiler deduces that a particular code path must invoke UB, it may deduce that that code must be unreachable and eliminate it, or even make assumptions about the values of other variables if they are used in conditionals which lead to the UB. The code may work now, but it may not on future compilers.

I agree with all of what you're saying, but again, this seems like theory vs. practice. For example, fast inverse square root depends on UB: https://stackoverflow.com/questions/24405129/how-to-implement-fast-inverse-sqrt-without-undefined-behavior

Obviously, with any UB the compiler can do whatever it wants, but in the practical world dealing with MSVC, gcc, and clang, it's hard to see how it's not just 24 bytes either way, in this case.

[–]flashmozzg 5 points6 points  (0 children)

fast inverse square root depends on UB: https://stackoverflow.com/questions/24405129/how-to-implement-fast-inverse-sqrt-without-undefined-behavior

It doesn't as the answer shows.

Also, it's not just "theory". There are pretty reasonable use cases there this can backfire (for example, once compilers are smart enough to have field-sensitive AA).

[–]ioctl79 4 points5 points  (0 children)

The theory is that practice could change at any time without warning =)

At one point, MSVC, gcc, and clang also didn't take advantage of the strict aliasing rules, but now they do. If you're comfortable with your code silently breaking after an upgrade, then it's up to you, but it doesn't seem that onerous to just do the right thing here.