2

We get an ArithmeticException (Overflow or underflow in the arithmetic operation.) in the following line on a customer machine. We are not able to reproduce it on any PC (customers or ours):

var actualFullness = (byte)((hdd.Capacity - hdd.FreeSpace) / (float)hdd.Capacity * 100);

where hdd.Capacity and hdd.FreeSpace are uint. Values are from function in native DLL.

We use NO checked or unchecked keywords in program. We do NOT use /checked compiler option.

It is written in .NET 4 and is running as 32-bit process.

Any idea why this exception is thrown?

Jehof
  • 34,674
  • 10
  • 123
  • 155
tom.maruska
  • 1,411
  • 16
  • 22
  • 4
    uint/float and you cast it to byte? – Andrew Apr 23 '14 at 09:13
  • 2
    Have you logged the values of `Capacity` and `FreeSpace` before the arithmetic is performed? That would help with diagnosis. – Jon Skeet Apr 23 '14 at 09:16
  • Is that possible that your capacity is less then freespace (because of whatever reason), and then that would result in negative value – Andrew Apr 23 '14 at 09:18
  • Why use another DLL to get this information? WMI (eg. from `Win32_LogicalDricve`). Worth noting the FreeSpace and Capacity values in WMI are `uint64`. A partition of more than 4GB will cause overflow problems in that expression. – Richard Apr 23 '14 at 09:22
  • While this seems like a very interesting problem, I'm voting to close this as "lacking sufficient information" simply because there are far too many unknowns here for anyone to be able to answer conclusively. What is the output of the DLL? What units are we talking about? What is the capacity and freespace values of the hard drive where this exception is being thrown? Are the capacity and freespace values accurate (meaning are the values you are getting from the DLL consistent with with what WMI is telling you)? – psubsee2003 Apr 23 '14 at 09:42
  • @psubsee2003 i don't think it's important to know what units we are talking about. – tom.maruska Apr 23 '14 at 10:47
  • @Richard external dll provides me capacity and free space of remote device (DVR). – tom.maruska Apr 23 '14 at 10:49
  • @Jon Skeet i haven't log it yet, but i certainly will :] – tom.maruska Apr 23 '14 at 10:51

2 Answers2

0

ArithmeticException is the base class for DivideByZeroException, NotFiniteNumberException, and OverflowException. In general, one of the derived classes of ArithmeticException will be thrown to more precisely indicate the exact nature of the error.

Since you didn't get any of those more specific ones, than there's something wrong behind your expression. A Capacity or FreeSpace getter are candidates to look into.

I've checked the following code for different scenarios and if worked

uint Capacity = 100; //110; uint.MaxValue;  0
uint FreeSpace = 110;//100; 0;              uint.MaxValue
var actualFullness = (byte)((Capacity - FreeSpace) / (float)Capacity * 100);
Andrew
  • 3,648
  • 1
  • 15
  • 29
0

The exception is not raised by the arithmetic shown in the question. This program covers the edge cases and runs perfectly fine:

class Program
{
    static byte test(uint capacity, uint free)
    {
        return (byte)((capacity - free) / (float)capacity * 100);
    }

    static void Main(string[] args)
    {
        Console.WriteLine(test(uint.MaxValue, uint.MaxValue));
        Console.WriteLine(test(0, 0));
        Console.WriteLine(test(uint.MaxValue, 0));
        Console.WriteLine(test(0, uint.MaxValue));
    }
}

In fact it is easy enough to see by static analysis that the expression in the question is not responsible for the error.

So you do appear to have mis-diagnosed the fault. Perhaps the native code you refer to is somehow triggering the exception. At any rate, the only thing to say is that you need to dig deeper and try to obtain a correct diagnosis of the problem.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490