System.DivideByZeroException

The exception that is thrown when there is an attempt to divide an integral or <code>Decimal</code> value by zero.

Minimum version: >= 1.1 >= Core 1.0

Statistics

24
elmah.io logo 17
25

How to handle it

try
{

}
catch (System.DivideByZeroException e)
{

}
try
{

}
catch (System.DivideByZeroException e) when (e.Message.Contains("something"))
{

}
try
{

}
catch (System.DivideByZeroException e) when (LogException(e))
{

}

private static bool LogException(Exception e)
{
    logger.LogError(...);
    return false;
}

How to avoid it

Before
int dividend = 10;
int divisor = 0;

try
{
    int result = dividend / divisor;
}
catch (DivideByZeroException e)
{
}
After
int dividend = 10;
int divisor = 0;

if (divisor > 0)
{
    int result = dividend / divisor;
}

Links

YouTube videos

Possible fixes from StackOverflow

You should get all of this by simply calling the .ToString() method of the exception. We use this to log information and you get everything that I believe you are asking for. See MSDN System.Exception.ToString() for more information.

The reason of divide by zero here is not really related to truncating result when casting Math.Pow(x, 0) to int. Math.Pow(x, 0) will always return 1, and casting it to int will give you 1. Reason is integer overflow. For example consider:

var pow = (int)Math.Pow(10, 10);

10^10 does not fit into int size, so it will overflow (multiple times), and variable pow will have value -2147483648. When you multiply that by 10, it again overflows and result is 0. At this point you get your divide by zero exception.

To avoid such bizzare results you might want to do arithmetic operations that might unexpectedly result in overflow in checked context:

checked {
    var pow = (int) Math.Pow(10,10); 
    // throws overflow exception so you can fix your buggy code early
}

Of course at that point you already realize that your algorithm to reverse number is not a good one, so refer to another answer for a better way.

I got something working by emitting an (in-memory) assembly with debug information.

Example code:

var code = @"
var a = 0;
var b = 1 / a;
";

var script = CSharpScript.Create(code);
var compilation = script.GetCompilation();
var ilstream = new MemoryStream();
var pdbstream = new MemoryStream();
compilation.Emit(ilstream, pdbstream);

var assembly = Assembly.Load(ilstream.GetBuffer(), pdbstream.GetBuffer());
var type = assembly.GetType("Submission#0");
var factory = type.GetMethod("<Factory>");
var submissionArray = new object[2];
Task<object> task = (Task<object>)factory.Invoke(null, new object[] { submissionArray });

try
{
    await task;
}
catch (DivideByZeroException dbze)
{
    Console.WriteLine(dbze.StackTrace);
}

The output is (notice the :line 3 in the stack trace):

   at Submission#0.<<Initialize>>d__0.MoveNext() in :line 3
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at UnitTests.ExploreRoslyn.<ExploreEmittingAssembly>d__13.MoveNext() in D:\dev\misc\netmockery\UnitTests\ExploreRoslyn.cs:line 151

Now obviously this is a bit of a hack, and I'm not really happy with the hardcoded script engine implementation details (Submission#0, <Factory>), plus I don't really know what I'm doing. There should be (and maybe there is?) a better way.

Update

Created issue https://github.com/dotnet/roslyn/issues/13482 in the Roslyn issue tracker.

There are two issues with your code:

  1. In the first version, you're catching Exception, which means that when the Assert.Fail is reached and throws AssertionException, that exception is then caught and ignored.

    This means that there is no difference between RunAsync and delegate here, neither of them throws DivideByZeroException.

  2. Both RunAsync and the ScriptRunner<T> delegate return Task. That means to actually wait for them to complete or to observe any exceptions, you need to use await. Once you do that, you will see the DivideByZeroException that you're expecting.

You are encountering limitations of computer-based arithmetic. (Another answer shows the details which I were incorrect in previous versions of my answer.) To avoid these details entirely, you can divide by 10 at the end of each iteration of the loop:

while (x > 0)
{
    int endDig = x % 10;
    //...
    x /= 10;
}

Now you no longer need to worry the limits of int because your number will never be larger than the original input.