[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 

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+}

   Classes, SysUtils, Crt;

// {$R *.res}

   x: double;

   // Successful Test:  (Win64 + Linux)
   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('Setting Variable: x := 0.35; ');
   x := 0.35;
   WriteLn('FloatToStr( x )    --> ',FloatToStr(x));
   WriteLn('FloatToStr( 0.35 ) --> ',FloatToStr(0.35));


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


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


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,

More information about the lazarus mailing list