Recent

Author Topic: Inconsistency between Windows and Linux compiling?  (Read 23848 times)

Alex Kidd

  • New member
  • *
  • Posts: 9
Inconsistency between Windows and Linux compiling?
« on: June 11, 2011, 06:13:26 pm »
I began experimenting with Lazarus, using Moraz Abdel Azeem's Start programming using Object Pascal.

I stumbled upon this issue compiling this simple program (excerpt):

Code: [Select]
var
  x,y:integer;
  res:double;
begin
  x:=5;
  y:=0;
  try
[color=red]    res:=x/y;[/color]
  except on e:exception do
      writeln('Exception:',e.message); [actually, I'm using a Memo]
  end;

  writeln('Res:',floattostr(res));  [actually, I'm using a Memo]
end;                                    

If I compile and run this code in Windows, a DivideByZero exception is raised, which is correct.  :D
On the other hand, if I compile and run this code in Linux, no exception is raised: the variable res is set to "+inf" value.  :o

Is there a particular compiler flag I have to set in Linux to obtain the correct behaviour?

Please, let me know!
« Last Edit: June 12, 2011, 11:14:32 am by Alex Kidd »

eny

  • Hero Member
  • *****
  • Posts: 1587
Re: Inconsistency between Windows and Linux compiling?
« Reply #1 on: June 11, 2011, 07:00:51 pm »
If I compile and run this code in Windows, a DivideByZero exception is raised, which is correct.  :D

What Lazarus and FPC version?
When I do this the program crashes horribly.
(BTW: dividing through zero is not the best of ideas...)
All posts based on: Win10 (Win64); Lazarus 1.8.0 'stable' (#56594 win64) unless specified otherwise...

Alex Kidd

  • New member
  • *
  • Posts: 9
Re: Inconsistency between Windows and Linux compiling?
« Reply #2 on: June 12, 2011, 08:08:03 am »
If I compile and run this code in Windows, a DivideByZero exception is raised, which is correct.  :D

What Lazarus and FPC version?
When I do this the program crashes horribly.
(BTW: dividing through zero is not the best of ideas...)

Lazarus 0.9.30 and FPC 2.4.2.
I agree "divide by zero" is not the best of ideas  ;), I was just trying the samples in the book and make a comparison between Linux Mint 10 and Windows XP SP3 to verify the behaviour is exactly the same.

Apparently they differ: WinXP raises the exception, while Linux says the result is +Infinite.

This means in this particular case I cannot write the code once and compile everywhere. I think this is normal when coding using DLLs or OS specific features, but not when using simple math functions.

 

Zoran

  • Hero Member
  • *****
  • Posts: 1464
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Inconsistency between Windows and Linux compiling?
« Reply #3 on: June 12, 2011, 09:08:42 am »
Alex, what output do you get from this program if exception doesn't get raised?

I have just tried and compiled this example on Linux (Ubuntu 11.04). The exception gets raised as expected.
When I enter zero for y, I receive the message "An error occurred: Division by zero", which means that the execution fell into "except" branch of try-except block.

Further, if I change the writeln to
Code: [Select]
Writeln('An error occurred: ', e.ClassName, ' - ', e.message); (that is, add e.ClassName to output), I can see that EDivByZero got raised (I get: "An error occurred: EDivByZero - Division by zero").
« Last Edit: June 12, 2011, 09:10:47 am by Zoran »

Blaazen

  • Hero Member
  • *****
  • Posts: 2782
  • POKE 54296,15
    • Eye-Candy Controls
Re: Inconsistency between Windows and Linux compiling?
« Reply #4 on: June 12, 2011, 09:44:47 am »
Here I also get:
Code: [Select]
Res:+Inf
I think it is correct because "/" is used and "res" is double.

If I replace "/" with "div" project gives SIGFPE - invalid floating point operation.
It is also correct because result of "div" cannot be +Inf and therefore there is no result which can be assigned to "Res".
Lazarus 2.1.0 r61214:62238 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Alex Kidd

  • New member
  • *
  • Posts: 9
Re: Inconsistency between Windows and Linux compiling?
« Reply #5 on: June 12, 2011, 10:14:36 am »
Blaazen, which Linux distro are you using?

It seems you and Zoran are experimenting different outputs. I tried also Mint 11, and still I get the +inf behaviour (with no exception).

I get the SIGFPE error too when using DIV instead of "/" (the exception is EInvalidOp, Invalid floating point operation).  :D

Zoran, what disto / fpc version are you using by the way?

I think something strange is going on here...  8-)

Alex Kidd

  • New member
  • *
  • Posts: 9
Re: Inconsistency between Windows and Linux compiling?
« Reply #6 on: June 12, 2011, 10:36:14 am »
Well, maybe the title I used in the topic is incorrect. I think I found out the difference is not between the Linux and WinXP version, but between "Application" and "Program".

The application shows the +inf behaviour, while the program behaves like Zoran's test.

Here are the two codes:
APPLICATION
Code: [Select]
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
  { TForm1 }
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation
{$R *.lfm}
{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var
  x,y:integer;
  res:double;
begin
  x:=5;
  y:=0;

  try
    res:=x / y;
  except on e:exception do
    memo1.append(e.message);
  end;

  memo1.append(floattostr(res));
end;
end.              


PROGRAM
Code: [Select]
program Project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes,sysutils
  { you can add units after this };

{$R *.res}

var
  x,y:integer;
  res:double;

begin
  x:=5;
  y:=0;

  try
    res:=x / y;
  except on e:exception do
    writeln(e.message);
  end;

  writeln(floattostr(res));
end.      

Later on I'm going to reboot to winxp and test if my theory is confirmed (i.e. I was really wrong suspecting Lin and Win compile differently...  O:-)).
« Last Edit: June 12, 2011, 11:15:32 am by Alex Kidd »

Alex Kidd

  • New member
  • *
  • Posts: 9
Re: Inconsistency between Windows and Linux compiling?
« Reply #7 on: June 12, 2011, 11:04:14 am »
Back on line.

I tested the two codes in WinXP and I always got the Divide By Zero exception.

My suspect is that in the Application version in Linux Mint 10 and 11 (and the distro used by Blazeen) the compiler somehow think 5/0 is a valid operation, and the risult is +inf.

Help!!!   %)

Blaazen

  • Hero Member
  • *****
  • Posts: 2782
  • POKE 54296,15
    • Eye-Candy Controls
Re: Inconsistency between Windows and Linux compiling?
« Reply #8 on: June 12, 2011, 11:25:32 am »
My first attempt was in Chakra (Arch-based linux). I rebooted to Kubuntu with the same result (Res:+Inf). (both are 64-bit)

Then I tried compile it without Lazarus from console (fpc filename.pas - without compiler options). I tried both as program and as unit - both gives Division by Zero.

So it is not distro related. It must be some special compiler option which Lazarus uses but I don't know which, they are so many.
Lazarus 2.1.0 r61214:62238 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Bart

  • Hero Member
  • *****
  • Posts: 3539
    • Bart en Mariska's Webstek
Re: Inconsistency between Windows and Linux compiling?
« Reply #9 on: June 12, 2011, 11:45:55 am »
Might have something to do with the exceptionmask (unit math)?

Bart

Laksen

  • Hero Member
  • *****
  • Posts: 621
    • J-Software
Re: Inconsistency between Windows and Linux compiling?
« Reply #10 on: June 12, 2011, 11:53:48 am »
It's probably libraries of the host system that are overriding the exception mask, as Bart suggests. If it's a big problem then include the math unit, and in the start of the program do SetExceptionMask([]);

Alex Kidd

  • New member
  • *
  • Posts: 9
Re: Inconsistency between Windows and Linux compiling?
« Reply #11 on: June 12, 2011, 05:36:24 pm »
It's probably libraries of the host system that are overriding the exception mask, as Bart suggests. If it's a big problem then include the math unit, and in the start of the program do SetExceptionMask([]);

I tried the SetExceptionMask suggestion and it works  ;D

Thank you so much to all users who kindly answered my question.

Lazarus is a fantastic project and I think it's gonna replace very soon Java, Mono and Python for my cross-platform needs (especially the GUI related). I just need to experiment some more.

In the meanwhile I'm spreading the voice with my colleagues, showing the capabilities of Lazarus. A couple of Delphi nostalgic didn't even know there was an open source project going on and now are thanking me for the hint!

Zoran

  • Hero Member
  • *****
  • Posts: 1464
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Inconsistency between Windows and Linux compiling?
« Reply #12 on: July 01, 2011, 07:24:50 pm »
What is actually this ExceptionMask?
I can't find anything in documentation. %)
And I think that this diferrent behavior is not a minor thing, I realy would like to understand what it is about.

Laksen

  • Hero Member
  • *****
  • Posts: 621
    • J-Software
Re: Inconsistency between Windows and Linux compiling?
« Reply #13 on: July 01, 2011, 10:23:36 pm »
The exception mask is the mask for exceptions coming from the FPU :)

So if it's entirely unmasked(as is the default for FreePascal) all exceptional behaviour will generate an exception. However if it's masked, either entirely or partly(as is the default for some C programs), the operation will go unnoticed: 1/0 will become +Inf, log(0) will be NaN, etc

The FreePascal RTL does clear this exception mask when the program starts, but if the program subsequently loads DLLs or SOs that override the exception mask for the process then the program won't be notified. And it can go the other way too. Some C DLL/SOs might "randomly" generate exceptions because they might rely on unsafe FPU operations :)

Zoran

  • Hero Member
  • *****
  • Posts: 1464
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Inconsistency between Windows and Linux compiling?
« Reply #14 on: July 03, 2011, 12:23:19 pm »
It's probably libraries of the host system that are overriding the exception mask, as Bart suggests.
If I understand correctly, this means that if some library is called by the application and that library changes this exception mask for its own purposes, than the whole program will change its exception handling?! :o

If it's a big problem then include the math unit, and in the start of the program do SetExceptionMask([]);

Does not work. Setting the ExceptionMask to empty set in program start creates many new exceptions and the application crashes.

There are problems even if the ExceptionMask is set for this simple isolated line:
Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var
  X, Y: Integer;
  Res: Double;
  FPUExceptionMask: TFPUExceptionMask;
begin
  X := StrToInt(Edit1.Text);
  Y := StrToInt(Edit2.Text);
  try
    FPUExceptionMask := SetExceptionMask([]);
    try
      Res := X / Y; // I set ExceptionMask only for this line of code
    finally
     SetExceptionMask(FPUExceptionMask); // and restore it back
    end;

    Label3.Caption := FloatToStr(Res);
  except
    on E: Exception do
      Label3.Caption := E.ClassName + ' - ' + E.Message;
  end;

end;
Now it raises EInvalidOp, when I use non-divisible integers, although the result is regularly stored in Double, something which works well if I do not mess with ExceptionMask (see the picture).
« Last Edit: July 03, 2011, 12:26:06 pm by Zoran »