6

If I pass Int32.MinValue and -1 into the Divide() method, I get a System.OverflowException despite the block happening in an unchecked block.

    private static int Divide(int n, int d)
    {
        return unchecked (n / d);
    }

This is surprising to me - unless I've read the documentation for checked / unchecked incorrectly, I'd expect it to just give me an overflowed output (since Int32.MinValue / -1 = 2^31 = Int32.MaxValue + 1, I was expecting an overflow to a value of Int32.MinValue). Instead it threw an OverflowException.

Here's a DotNetFiddle showing the issue.

will_w
  • 73
  • 6

1 Answers1

2

From the C# draft specification on integer division:

If the left operand is the smallest representable int or long value and the right operand is -1, an overflow occurs. In a checked context, this causes a System.ArithmeticException (or a subclass thereof) to be thrown. In an unchecked context, it is implementation-defined as to whether a System.ArithmeticException (or a subclass thereof) is thrown or the overflow goes unreported with the resulting value being that of the left operand.

I'm not sure where Microsoft lists its choices for implementation-defined behavior, but apparently they chose the first option here.

This and other implementation-defined or undefined behavior is listed in Annex B of ECMA-334. The draft specification above is updated more recently, but it seems to lack this annex.

Joe Sewell
  • 4,871
  • 1
  • 19
  • 29
  • 2
    That answers it pretty clearly. Your answer made me try to see if the behavior changed in any other of the compilers supported by DotnetFiddle. All of them produce the same result. It is a little counterintuitive to see an OverflowException pop out of a checked block, though. – will_w Feb 05 '21 at 18:03