Hacker News new | past | comments | ask | show | jobs | submit login

Could you provide the code you use to trivially catch signed overflows? My impression is the opposite: unsigned is trivial (just test `a+b < b`) while signed is annoying (especially because evaluating a potentially-overflowing expression would cause the UB I'm trying to avoid).



Oh, I meant it is trivial to catch bugs caused by overflow by using a sanitizer and difficult to find bugs caused by wraparound.

But checking for signed overflow is also simply with C23: https://godbolt.org/z/ebKejW9ao


>unsigned is trivial (just test `a+b < b`)

Nitpicking, the test itself should avoid overflowing. Instead, test "a <= UINT_MAX - b" to prove no overflow occurs.

For signed integers, we need to prove the following without overflowing in the test: "a+b <= INT_MAX && a+b >= INT_MIN". The algorithm follows: test "b >= 0", which implies "INT_MAX-b <= INT_MAX && a+b >= INT_MIN", so then test "a <= INT_MAX-b". Otherwise, "b < 0", which implies "INT_MIN-b >= INT_MIN && a+b <= INT_MAX", so then test "a >= INT_MIN-b".


> Nitpicking, the test itself should avoid overflowing.

Why? Overflowing is well defined for unsigned.


Personal preference, hence nitpicking. It forms a special case of the signed integer algorithm, which feels nice.


Compiling with -ftrapv will cause your program to trap on signed overflow/underflow, so when you run it in a debugger you can immediately see where and why the overflow/underflow occurred.


It's worth mentioning that GCC's ftrapv has been unreliable and partially broken for 20+ years at this point. It's recommended that you use the fsanitize traps instead, and there's an open ticket to switch the ftrapv implementation over to using it under the hood:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101521


Thanks, I hadn't heard of that.


You're right that this test would be UB for signed integers.

See here for that in action, as well as one way to test it that does work: https://godbolt.org/z/sca6hxer4

If you're on C23, uercker's advice to use these standardized functions is the best, of course.


Avoiding UB for performing the signed addition/subtraction/multiplication is trivial - just cast to unsigned, do the operation, cast back. In standard C23 or GNU C11, you can write a `make_unsigned` and `make_signed` macro using `typeof` and `_Generic`.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: