[Lazarus] Cross-compile for Linux strange behaviour with floating point constants
R Smith
ryansmithhe at gmail.com
Wed Nov 20 19:19:45 CET 2019
Hi All,
I'm a long time Lazarus user (since Kylix failed) and a big fan. This is
however my first post on any FPC/Lazarus forum.
The problem I've run into is a simple program (made in Lazarus) where I
use floating point constants. It compiles and runs perfectly on Windows,
but when cross-compiling for Linux, it fails for specific floating point
values.
I realise immediately that, if this is a bug, it's probably an FPC bug
and not Lazarus specific, but the problem is so obviously wrong, I'm
thinking it cannot possibly be a compiler bug, and since I am
cross-compiling from Lazarus, figured I would start asking here and rule
out the obvious things first.
1. My Setup:
Fresh install of Lazarus IDE (SVN Revision 60307 - previous install also
had the problem, so I updated) with FPC 3.04 installed on Windows 10
64bit (x86_64-win64) via fpcupdeluxe with compilers for Windows x86_64
and for Linux x86_64. I run WSL Ubuntu 19.4 and also 18.4 in a VM and
CentOS7 (because web), and a Linux Mint on my laptop, all of which get
the same error. It compiles and runs perfectly correct in/for Windows.
2. Test case Program:
---------------------------------------------------
program fpbug;
// {$mode objfpc}{$H+}
uses
Classes, SysUtils, Crt;
// {$R *.res}
var
x: double;
begin
// Successful Test: (Win64 + Linux)
WriteLn('');
WriteLn('Setting Variable: x := 0.5; ');
x := 0.5;
WriteLn('FloatToStr( x ) --> ',FloatToStr(x));
WriteLn('FloatToStr( 0.5 ) --> ',FloatToStr(0.5));
// Failing Test: (Win64 Pass, Linux Fail (Ubuntu LTS)
WriteLn('');
WriteLn('Setting Variable: x := 0.35; ');
x := 0.35;
WriteLn('FloatToStr( x ) --> ',FloatToStr(x));
WriteLn('FloatToStr( 0.35 ) --> ',FloatToStr(0.35));
end.
----------------------------------------------
I compile with standard debug options first, then production options
(both Windows and Linux with CPU family x86_64 and target Processor
Default) and had an exhaustive run of enabling/disabling every compiler
switch available in the standard Lazarus "Compilation and Linking"
settings - all to no avail, the problem persists.
3. Windows console Output:
C:\Projects\[LAZARUS]\Temp\ConsoleAppTest>dir /w
Volume in drive C has no label.
Volume Serial Number is C234-0116
Directory of C:\Projects\[LAZARUS]\Temp\ConsoleAppTest
[.] [..] [backup] fpbug fpbug.dbg
fpbug.exe fpbug.lpi fpbug.lpr fpbug.lps
fpbug.res fptest fptest.dbg fptest.exe fptest.lpi
fptest.lpr fptest.lps fptest.res [lib]
rc rc.exe rc.lpi rc.lpr rc.lps
19 File(s) 2 547 273 bytes
4 Dir(s) 88 585 740 288 bytes free
C:\Projects\[LAZARUS]\Temp\ConsoleAppTest>fpbug
Setting Variable: x := 0.5;
FloatToStr( x ) --> 0.5
FloatToStr( 0.5 ) --> 0.5
Setting Variable: x := 0.35;
FloatToStr( x ) --> 0.35
FloatToStr( 0.35 ) --> 0.35
C:\Projects\[LAZARUS]\Temp\ConsoleAppTest>
4. Linux console Output:
cuzzy at CUZ-PC64:~/temp/ConsoleAppTest$ ls
backup fpbug.dbg fpbug.lpi fpbug.lps fptest fptest.exe fptest.lpr
fptest.res rc rc.lpi rc.lps
fpbug fpbug.exe fpbug.lpr fpbug.res fptest.dbg fptest.lpi
fptest.lps lib rc.exe rc.lpr
cuzzy at CUZ-PC64:~/temp/ConsoleAppTest$ ./fpbug
Setting Variable: x := 0.5;
FloatToStr( x ) --> 0.5
FloatToStr( 0.5 ) --> 0.5
Setting Variable: x := 0.35;
FloatToStr( x ) --> 0.35
FloatToStr( 0.35 ) --> Nan
cuzzy at CUZ-PC64:~/temp/ConsoleAppTest$
As the comments indicate, if I use the constant value 0.5 inside almost
any function that takes a float (Double, Extended, Real, whatever), it
works, both in Windows and Linux.
If I use the value 0.35 (or 0.66667 or 0.333333 - seemingly any number
that has a non-exact round-trip IEEE754 representation, but this is
merely a guess, no exhaustive testing) then in Windows on x86-64 it
still works as expected, but on any Linux version, it returns NaN (as in
my code example) or segfaults or such.
It is perfectly happy for me to assign the value to a variable and then
use the variable (x in the example), but when I use the value directly,
the skullduggery starts.
Tested functions (they all fail for a constant like 0.35): FloatToStr(),
Trunc(), Round(), Ceil(), Floor()
Is there something I can check on my side? Does this work for others?
Might this be a cross-compile bug of sorts? Is this some FPC, FPU or
Linux peculiarity I'm not aware of?
Any help or insight would be appreciated - thanks,
Cuz
More information about the lazarus
mailing list