April 15, 2007
Hello,

is it possible to check for integer overflows?


$ cat test.d; dmd -w *.d; ./test
import std.stdio;
int main(char[][] args)
{
        uint i = 0, j = uint.max;;
        writefln("i = ",i, ";j = ",j);
        try
        {
                --i;++j;
        }
        catch (Exception e)
        {
                writefln("exception!");
        }
        writefln("i = ",i, ";j = ",j);
        return 0;
}

gcc test.o -o test -m32 -lphobos -lpthread -lm
i = 0;j = 4294967295
i = 4294967295;j = 0

Where is my fault?

Sebastian
April 15, 2007
Sebastian Philipp schrieb am 2007-04-15:
> Hello,
>
> is it possible to check for integer overflows?

Yes.

> $ cat test.d; dmd -w *.d; ./test
> import std.stdio;
> int main(char[][] args)
> {
>         uint i = 0, j = uint.max;;
>         writefln("i = ",i, ";j = ",j);
>         try
>         {
>                 --i;++j;
>         }
>         catch (Exception e)
>         {
>                 writefln("exception!");
>         }
>         writefln("i = ",i, ";j = ",j);
>         return 0;
> }
>
> gcc test.o -o test -m32 -lphobos -lpthread -lm
> i = 0;j = 4294967295
> i = 4294967295;j = 0
>
> Where is my fault?

The code is behaving as designed (silent overflow).

One way to throw an exception if an uint addition overflows can be found below:

# uint add(uint a, uint b){
#    version(DigitalMars){
#       asm{
#          naked;
#          add EAX, dword ptr [EBP+8];
#          jc Loverflow;
#          ret;
#       }
#    Loverflow:
#       throw new Exception("overflow");
#    }else{
#       // unoptimized
#       ulong l = a;
#       l += b;
#       if(l > uint.max){
#          throw new Exception("overflow");
#       }else{
#          return cast(uint)l;
#       }
#    }
# }
#
# import std.stdio;
# int main(){
#    writefln("%s", add(1, 2));
#    writefln("%s", add(1, uint.max));
#    return 0;
# }

Thomas