Recent

Author Topic: Detecting division by zero  (Read 11430 times)

Daniello

  • Jr. Member
  • **
  • Posts: 64
Detecting division by zero
« on: December 06, 2013, 01:49:00 pm »
Hi guys!
I always ignored division by zero until now, when I found out that Android apps made with free pascal crash hard when they reach a division by zero.
I have a game that works fine on Windows, but on Android sometimes crashes with a cryptic crash dump, that I think it is probably caused by a division by zero.

My question is, is there a way to detect divisions by zero in fpc, by way of exceptions or something?
I want to detect all divisions by error when running the game (on Windows for example, it might be easier), and then write code to handle them correctly, and thus, hopefully stopping the Android version from crashing.

So, is there a way to automatically detect a line of code that does a division by zero at run time?
I can't really just search in the code, mostly because the code base is huge (150 thousand lines) and the division symbol is easily confused with the comment symbol, so it is very hard to search  ::)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12721
  • FPC developer.
Re: Detecting division by zero
« Reply #1 on: December 06, 2013, 01:58:27 pm »

The exceptions are sysutils.Edivbyzero for integer divisions and sysutils.ezerodivide.for floating point.

It might also be possible that badly written external (non pascal) code suddenly starts throwing exceptions because they were developed with exceptions off.

In that case have a look at Setexceptionmask  (search the web for examples)

Daniello

  • Jr. Member
  • **
  • Posts: 64
Re: Detecting division by zero
« Reply #2 on: December 06, 2013, 02:05:51 pm »
Thanks!
My understanding of this is that I can for example put a big Try Except block on my game and catch all divisions by zero, but when an division by zero exception is catched, the debugger will stop at the exception block right?
Is there anyway to find the original line of code that caused the exception?

Zoran

  • Hero Member
  • *****
  • Posts: 1988
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Detecting division by zero
« Reply #3 on: December 06, 2013, 02:06:30 pm »
There is also problem that some widgetsets change exception mask (like gtk2, see: http://wiki.lazarus.freepascal.org/Multiplatform_Programming_Guide#Gtk2_and_masking_FPU_exceptions), perhaps you should check the exception mask first.
Swan, ZX Spectrum emulator https://github.com/zoran-vucenovic/swan

Daniello

  • Jr. Member
  • **
  • Posts: 64
Re: Detecting division by zero
« Reply #4 on: December 06, 2013, 02:11:20 pm »
There is also problem that some widgetsets change exception mask (like gtk2, see: http://wiki.lazarus.freepascal.org/Multiplatform_Programming_Guide#Gtk2_and_masking_FPU_exceptions), perhaps you should check the exception mask first.
I am not using Widgets, but I change the mask myself manually at startup (because of using OpenGL, it is necessary).
I don't have acess to the code now, but later I will check, I just find it strange that on Android a division by zero instantly crashes the game, while on iOS, Linux, Windows etc the exactly same code runs fine, I'm pretty sure all versions use the same exception mask, but I will double check to make sure

Bart

  • Hero Member
  • *****
  • Posts: 5706
    • Bart en Mariska's Webstek
Re: Detecting division by zero
« Reply #5 on: December 06, 2013, 05:56:43 pm »

The exceptions are sysutils.Edivbyzero for integer divisions and sysutils.ezerodivide.for floating point.

Not true (at least on Windows). Both floating point and integer division by zero raise an EDivByZero exception:
Code: [Select]
program test;

{$mode objfpc}
//{$H-}

uses
  SysUtils, Classes;

var
  F: Double;
  I: Integer;

begin
  F := 0.0;
  I := 0;
  try
    write('1 div ',I,' -> ');
    I := 1 div I;
    writeln(I);
  except
    on E: Exception do writeln(E.ClassName);
  end;
  try
    write('1 / ',F:2:2,' -> ');
    F := 1 / F;
    writeln(F);
  except
    on E: Exception do writeln(E.ClassName);
  end;
end.

Code: [Select]
C:\Users\Bart\LazarusProjecten\ConsoleProjecten>fpc test.pas
Free Pascal Compiler version 2.6.2 [2013/02/12] for i386
Copyright (c) 1993-2012 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling test.pas
Linking test.exe
30 lines compiled, 3.0 sec , 134544 bytes code, 27356 bytes data

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>test
1 div 0 -> EDivByZero
1 / 0.00 -> EDivByZero

Bart

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12721
  • FPC developer.
Re: Detecting division by zero
« Reply #6 on: December 06, 2013, 06:29:25 pm »

Code: [Select]
1 div 0 -> EDivByZero
1 / 0.00 -> EDivByZero


Same on linux/32

Delphi:
Code: [Select]
1 div 0 -> EDivByZero
1 / 0.00 -> EZeroDivide

This is also what FPC documents

That's a bug I guess. Sysutils.inc holds a comment that both different exceptions map to the same runtime error, but the exception is different.

otorres

  • Jr. Member
  • **
  • Posts: 94
Re: Detecting division by zero
« Reply #7 on: December 06, 2013, 08:57:55 pm »
Code: [Select]
try
  {...}
except
  on EDivByZero do
    ShowMessage('Division by zero!')
  end;

Daniello

  • Jr. Member
  • **
  • Posts: 64
Re: Detecting division by zero
« Reply #8 on: December 06, 2013, 09:00:08 pm »
I found out that this line was missing from the Android port of the game:
  SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]);

With this, should happen no more crashes upon divisions by zero

Bart

  • Hero Member
  • *****
  • Posts: 5706
    • Bart en Mariska's Webstek
Re: Detecting division by zero
« Reply #9 on: December 06, 2013, 11:05:10 pm »
That's a bug I guess. Sysutils.inc holds a comment that both different exceptions map to the same runtime error, but the exception is different.

In past I have discussed that at length (I guess on FPC mailinglist), and IIRC it was deemed to be too cumbersome/difficult/impossible to implement cross-platform, and not important enough to fix that.

[edit]
Found the discussion at http://lists.freepascal.org/lists/fpc-pascal/2009-October/022851.html
[/edit]

Bart
« Last Edit: December 06, 2013, 11:21:20 pm by Bart »

 

TinyPortal © 2005-2018