Why dividing int.MinValue by -1 threw OverflowException in unchecked context?

Marcel Niehüsener
int y = -2147483648;
int z = unchecked(y / -1);

The second line causes an OverflowException. Shouldn't unchecked prevent this?

For example:

int y = -2147483648;
int z = unchecked(y * 2);

doesn't cause an exception.

Hans Passant

This is not an exception that the C# compiler or the jitter have any control over. It is specific to Intel/AMD processors, the CPU generates a #DE trap (Divide Error) when the IDIV instruction fails. The operating system handles the processor trap and reflects it back into the process with a STATUS_INTEGER_OVERFLOW exception. The CLR dutifully translates it to a matching managed exception.

The Intel Processor Manual is not exactly a gold mine of information about it:

Non-integral results are truncated (chopped) towards 0. The remainder is always less than the divisor in magnitude. Overflow is indicated with the #DE (divide error) exception rather than with the CF flag.

In English: the result of the signed division is +2147483648, not representable in an int since it is Int32.MaxValue + 1. Otherwise an inevitable side-effect of the way the processor represents negative values, it uses two's-complement encoding. Which produces a single value to represent 0, leaving an odd number of other possible encodings to represent negative and positive values. There is one more for negative values. Same kind of overflow as -Int32.MinValue, except that the processor doesn't trap on the NEG instruction and just produces a garbage result.

The C# language is of course not the only one with this problem. The C# Language Spec makes it implementation defined behavior (chapter 7.8.2) by noting the special behavior. No other reasonable thing they could do with it, generating the code to handle the exception surely was considered too unpractical, producing undiagnosably slow code. Not the C# way.

The C and C++ language specs up the ante by making it undefined behavior. That can truly get ugly, like a program compiled with the gcc or g++ compiler, typically with the MinGW toolchain. Which has imperfect runtime support for SEH, it swallows the exception and allows the processor to restart the division instruction. The program hangs, burning 100% core with the processor constantly generating #DE traps. Turning division into the legendary Halt and Catch Fire instruction :)

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Why does int.MinValue % -1 cause and OverflowException

Why evaluates "(Double.MinValue + 1) > Double.MinValue" to false?

Why does dividing a int with a float result in a float?

System.OverflowException in unchecked block of C#

Why does System.Decimal ignore checked/unchecked context

Why does the .Net implementation of Random.Next(int, int) require maxValue >= minValue?

Dividing string and converting to Int

Why is it not dividing correctly

Runtime error dividing by -1

Why does dividing two int not yield the right value when assigned to double?

Why is RadioGroup unchecked

Why unchecked not working on byte?

JavaScript Dividing Array Values by an Int

Dividing decimals and multiplying by an int to produce an int

Why is papaparse making incorrect subarrays? Dividing data into [0..99][100] array instead of [0][1]...[100]

Why has RISC-V output -1 or xFFFFFFFF from dividing by 0?

Why does +"1" return an int?

Why (1) is int and how it works

why threw an exception of type 'System.ArgumentException'

Servlet.service() for servlet [dispatcher] in context with path [/***] threw exception

'context.Request' threw an exception of type 'System.Web.HttpException'

Why the check box in simple_form view always returns 1 when being checked or unchecked in rails 3.2?

Why are exceptions named checked and unchecked?

Why is this an unchecked cast? And how to fix it?

Why runtime exception is unchecked exception?

Why are Runtime Exceptions "unchecked" in Java?

Why "Unchecked cast from..."

Why int[] a = new int[1] instead of just int a?

C# Random Seed Value of int.MinValue Unpredictable