Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

arithmetic exception in C#

Why in C# is Example A valid, compilable and will just wrap while examples B will not compile?

A

int val = 0;
val = val + Int32.MaxValue +2;

or

int val = Int32.MaxValue;
val++;

B

int val = 0;
val = 2147483647 + 1;

or

int val = 0;
int val = Int32.MaxValue + 1;

I know by default that arithmetic exceptions are not checked by default unless you explicitly do so using checked method, block or attribute in the config. My question relates more to compiler then how an arithmetic exception happens.

like image 899
Chris G Avatar asked Jul 16 '10 16:07

Chris G


People also ask

What is arithmetic exception in C?

ArithmeticException is the base class for the following exceptions: DivideByZeroException, which is thrown in integer division when the divisor is 0. For example, attempting to divide 10 by 0 throws a DivideByZeroException exception.

What is an arithmetic exception?

The arithmetic exception is a type of unusual outcome or unchecked error of the code, which is thrown or raised whenever a wrong mathematical or arithmetic operation appears in the code during run time.

Is arithmetic exception a runtime exception?

ArithmeticException inherits from the RuntimeException class which means it is an unchecked, runtime exception [2].

What causes arithmetic error?

An arithmetic exception is an error that is thrown when an invalid arithmetic situation occurs. This usually happens when mathematical calculation errors occur within a program at run-time.


2 Answers

Your B examples are constant-folded at compile time, indicating to the compiler that it's guaranteed to overflow.

Because your A examples use variables, the expressions cannot be (completely) constant-folded, so the compiler can't guarantee that the values will result in an overflow.

For instance...

int val = 0;
// some other thread changes `val` to -5...
val = val + Int32.MaxValue +2; // no overflow

However, if you know that val won't change, and assign 0 to a const int:

const int startval = 0;
int val = startval + Int32.MaxValue + 2;

You can get your compile-time overflow check back because the value can be completely determined and therefore constant-folded.

like image 135
Mark Rushakoff Avatar answered Oct 07 '22 08:10

Mark Rushakoff


I know that arithmetic exceptions are not checked by default unless you explicitly do so using checked method, block or attribute in the config

You do not know that because that statement is incorrect. And in fact you know it to be incorrect because you've provided a case where your statement is proven false!

I refer you to section 7.6.12 of the C# specification, a portion of which I reproduce here for your convenience:

For non-constant expressions (expressions that are evaluated at run-time) that are not enclosed by any checked or unchecked operators or statements, the default overflow checking context is unchecked unless external factors (such as compiler switches and execution environment configuration) call for checked evaluation.

For constant expressions (expressions that can be fully evaluated at compile-time), the default overflow checking context is always checked. Unless a constant expression is explicitly placed in an unchecked context, overflows that occur during the compile-time evaluation of the expression always cause compile-time errors.

See the spec for further details.

like image 43
Eric Lippert Avatar answered Oct 07 '22 08:10

Eric Lippert