Erfahrungsbericht/ Bug FormatSettings.DecimalSeparator

Für Fehler in Lazarus, um diese von anderen verifizieren zu lassen.

Erfahrungsbericht/ Bug FormatSettings.DecimalSeparator

Beitragvon corpsman » 27. Jul 2017, 05:53 Erfahrungsbericht/ Bug FormatSettings.DecimalSeparator

Servus mit einander,

hin und wieder habe ich böse Abstürze mit meinem Programm unter Windows 7.

Nach nun einer viel zu langen Zeit habe ich endlich eine Sequenz gefunden, mit derer ich den Bug nachstellen kann.

Mein Programm konvertiert Strings in Floats ala

Code: Alles auswählen
 
  f := strtofloat('1.0');
 


Natürlich habe ich im OnCreate ein

Code: Alles auswählen
 
  FormatSettings.DecimalSeparator := '.';   
 


Umstellen tue ich es nie mehr und doch bekomme ich nach einiger Nutzung immer eine AV nach dem Motto "1.0" is not a valid float.

Zum Nachstellen folgenden Code :

Code: Alles auswählen
 
Unit Unit1;
 
{$MODE objfpc}{$H+}
 
Interface
 
Uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
 
Type
 
  { TForm1 }
 
  TForm1 = Class(TForm)
    Button1: TButton;
    Procedure Button1Click(Sender: TObject);
    Procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  End;
 
Var
  Form1: TForm1;
 
Implementation
 
{$R *.lfm}
 
{ TForm1 }
 
Procedure TForm1.FormCreate(Sender: TObject);
Begin
  FormatSettings.DecimalSeparator := '.';
End;
 
Procedure TForm1.Button1Click(Sender: TObject);
Begin
  showmessage('FS : ' + FormatSettings.DecimalSeparator);
End;
 
End.
 


Des weiteren habe ich ein Deutsches Windows7, das Lazarus Programm wurde kompiliert unter einem Deutschen WinXP (default separator ist dort ',')
Wenn ich nun das Programm starte bekomme ich erwartungsgemäß die Meldung "FS : .". Den Bug erzeugen kann ich, wenn ich mittels WIN+L den Rechner Sperre und mich dann wieder einlogge. Danach kommt die Meldung "FS : ,"
Lazarus SVN Revision war : 54278
FPC Version : 3.0.2

Kann das jemand erklären / Reproduzieren ?
Muss ich in Zukunft in meine Programme einen Event "OnRelogin" einbauen der den DecimalSeparator wieder korrigiert ? Wie löst ihr das ?
Ist das evtl doch ein BUG ?

Unter Linux habe ich den Bug nicht, allerdings sind alle meine Linuxe auch default auf Eng -> Damit ist der DecimalSeparator eh schon auf "."

[Edit]
Selber Fehler reproduzierbar mit Delphi XE10 kompiliert und getestet unter Windows 7
--
Just try it
corpsman
 
Beiträge: 1078
Registriert: 28. Feb 2009, 08:54
Wohnort: Stuttgart
OS, Lazarus, FPC: Linux Mint Mate, Lazarus SVN Trunk, FPC 3.0 | 
CPU-Target: 64Bit
Nach oben

Beitragvon corpsman » 27. Jul 2017, 06:16 Re: Erfahrungsbericht/ Bug FormatSettings.DecimalSeparator

Also wenn man mal weis, wonach man suchen mus ...

Zumindest für Windows gobts das hier :

Code: Alles auswählen
 
{$IFDEF Windows}
  Application.UpdateFormatSettings := false;
{$ENDIF}
 


Gemäß https://stackoverflow.com/questions/981 ... ons-to-use

Passiert das tatsächlich immer, wenn der User geswitched wird.
Am besten ist wohl, wenn man sich in seiner Anwendung eine "Globale"
Code: Alles auswählen
 
var
  myFormatSettings: TFormatSettings;
 

macht und gibt diese an alle Routinen die man so nutzt mit.
=> Volle Kontrolle, aber doch eine ganze menge an Komfort welchen man hier verliert
--
Just try it
corpsman
 
Beiträge: 1078
Registriert: 28. Feb 2009, 08:54
Wohnort: Stuttgart
OS, Lazarus, FPC: Linux Mint Mate, Lazarus SVN Trunk, FPC 3.0 | 
CPU-Target: 64Bit
Nach oben

Beitragvon mse » 27. Jul 2017, 06:24 Re: Erfahrungsbericht/ Bug FormatSettings.DecimalSeparator

StrToFloat() gibt es in zwei Ausführungen:
Code: Alles auswählen
 
Function StrToFloat(Const S : String) : Extended;
Function StrToFloat(Const S : String; Const FormatSettings: TFormatSettings) : Extended;
 

In der Zweiten kann man eigene TFormatSettings übergeben, welche vom System nicht verändert werden. Die bei der ersten Form verwendeten DefaultFormatSettings werden den Systemeinstellungen nachgeführt. Offensichtlich löst Windows beim Einloggen einen Nachführvorgang aus -> bei festem Format sollten die Versionen der Konvertierungsfunktionen mit FormatSettings Parameter verwendet werden.
Eine Funktion string->real welche immer '.' als Dezimaltrenner verwendet ist "val":
https://www.freepascal.org/docs-html/cu ... m/val.html
Das Gegenstück dazu ist "str":
https://www.freepascal.org/docs-html/cu ... m/str.html
Edit: Wie du ja selbst herausgefunden hast. :-)
Zuletzt geändert von mse am 27. Jul 2017, 06:56, insgesamt 1-mal geändert.
mse
 
Beiträge: 2013
Registriert: 16. Okt 2008, 09:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0) | 
CPU-Target: x86,x64,ARM
Nach oben

Beitragvon corpsman » 27. Jul 2017, 06:50 Re: Erfahrungsbericht/ Bug FormatSettings.DecimalSeparator

Stelle das nun komplett um auf
Code: Alles auswählen
 
  strtofloat('1.0', DefFormat);   
 


So was geht dann leider auch nicht mehr :/
Code: Alles auswählen
 
s := SQLQuery1.Fields[*].AsString; // Wenn Fiels[*] ein Float ist, denn man aber als String raus reichen will
 


Na da hab ich wieder ne menge zu Tun bis das alles wieder sauber läuft. Immerhin weis ich nun woran es liegt, ...
--
Just try it
corpsman
 
Beiträge: 1078
Registriert: 28. Feb 2009, 08:54
Wohnort: Stuttgart
OS, Lazarus, FPC: Linux Mint Mate, Lazarus SVN Trunk, FPC 3.0 | 
CPU-Target: 64Bit
Nach oben

Beitragvon wp_xyz » 27. Jul 2017, 08:48 Re: Erfahrungsbericht/ Bug FormatSettings.DecimalSeparator

Die Frage ist: Wie kommt der Dezimalpunkt überhaupt in diesen String?

(1) Weil du als Programmierer meinst, Dezimalzahlen müssten mit Dezimalpunkt eingegeben werden? Dann stelle die Ländereinstellungen deines Betriebssystems entsprechend um, und du bist dieses "Problem" ein für alle mal los, nicht nur für dieses, sondern auch für alle anderen Programme. Sobald dein Programm aber auch von anderen Personen als dir selbst benutzt werden soll/kann, finde ich die Änderung der globalen FormatSettings in einem Programm unpassend und verwirrend. Denn es gibt nun mal Länder, in denen Dezimalzahlen mit Komma geschrieben werden, und das lernt man so schon in der Grundschule. Ein Programm, das die Gewohnheiten eines Benutzers ignoriert und ihm andere Einstellungen aufzwingt, ist benutzerunfreundlich und daher letztendlich unprofessionell.

(2) Weil du Dateien lesen/schreiben musst, die für alle Ländereinstellungen ohne Probleme lesbar sein sollen, also einen Dezimalpunkt enthalten? Dann würde ich zu Beginn der Lese/Schreibroutine eine lokale Kopie der FormatSettings erzeugen, dort den Dezimaltrenner auf Punkt setzen und diese lokalen Formatsettings in der String-Zahl-Konvertierungsroutine als letzten Parameter verwenden. Oder falls du dir sparen willst, alle Konvertierungs-Aufrufe zu ändern, kannst du auch die globalen FormatSettings umstellen, musst das aber am Ende wieder zurückstellen, am besten in einem try-finally-Block.
Code: Alles auswählen
procedure ReadSettings(AFilename: String);
var
  ds: Char;
begin
  ds := FormatSettings.DecimalSeparator;
  FormatSettings.DecimalSeparator := '.'
  try
    ...  // Datei einlesen
  finally
    FormatSettings.DecimalSeparator := ds;
  end;
end;
wp_xyz
 
Beiträge: 3006
Registriert: 8. Apr 2011, 08:01

Beitragvon Soner » 27. Jul 2017, 08:59 Re: Erfahrungsbericht/ Bug FormatSettings.DecimalSeparator

Ich ändere Formatsettings nie, wenn ich
und zu Floats mit '.' brauche wie z.B. in direkte SQL-Befehle, dann ersetze ich ',' durch '.' und benutze val. Ersetzen nur wenn das defaultseperator ungleich '.' Ist . İch have noch nie Ärger damit gehabt.
Auch Tausenderseparator ersetzen nicht vergessen.
Soner
 
Beiträge: 411
Registriert: 26. Sep 2012, 23:07
Wohnort: Hamburg
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes | 
CPU-Target: 32Bit
Nach oben

Beitragvon Timm Thaler » 27. Jul 2017, 12:13 Re: Erfahrungsbericht/ Bug FormatSettings.DecimalSeparator

wp_xyz hat geschrieben:Die Frage ist: Wie kommt der Dezimalpunkt überhaupt in diesen String?


Bei mir zum Beispiel über die RS232 aus einem externen Gerät. Da ist Dezimalseparator "." und Zahlenseparator ",". Und das kann ich auch nicht ändern.

Manchmal muss man also einfach da durch. Aber dass das automatisch wieder umgestellt werden kann wusste ich auch noch nicht. Ist das unter Linux auch so?
Timm Thaler
 
Beiträge: 985
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon wp_xyz » 27. Jul 2017, 12:20 Re: Erfahrungsbericht/ Bug FormatSettings.DecimalSeparator

Timm Thaler hat geschrieben:
wp_xyz hat geschrieben:Die Frage ist: Wie kommt der Dezimalpunkt überhaupt in diesen String?

Bei mir zum Beispiel über die RS232 aus einem externen Gerät. Da ist Dezimalseparator "." und Zahlenseparator ",". Und das kann ich auch nicht ändern.

Klar. Das wäre entsprechend dem Fall einer zu lesenden Datei. Mache dir eine lokale Kopie der FormatSettings mit Dezimalpunkt als Separator, und verwende diese in den StrToFloat-Aufrufen.

Timm Thaler hat geschrieben:Manchmal muss man also einfach da durch. Aber dass das automatisch wieder umgestellt werden kann wusste ich auch noch nicht. Ist das unter Linux auch so?

"das ... umgestellt"? Was meinst du?
wp_xyz
 
Beiträge: 3006
Registriert: 8. Apr 2011, 08:01

Beitragvon corpsman » 27. Jul 2017, 13:17 Re: Erfahrungsbericht/ Bug FormatSettings.DecimalSeparator

@wp_xyz

ich habe den Fall (2)
Mein Program arbeitet Plattform unabhängig auf Windows / Linux und De / En. Dabei müssen die Konfig Files überall geöffnet werden können. Deswegen habe ich da bisher immer alles auf '.' gestellt gehabt
=> Und ja es war so Ignorant, das es die Lokalen Einstellungen ignoriert hat. Rechtfertigen kann ich das nur dadurch, das meine Programme Grundsätzlich in English gehalten werden und daher dann die Zahlen auch in Englisch schreiben.

@Soner
So gings mir auch, ich habe nun ewig rumgesucht bis ich da mal drauf kam, dass Windwos die Formatsettings verändert.

Deswegen auch der Post um es anderen auch ins Gedächtnis zu Rufen ;)
--
Just try it
corpsman
 
Beiträge: 1078
Registriert: 28. Feb 2009, 08:54
Wohnort: Stuttgart
OS, Lazarus, FPC: Linux Mint Mate, Lazarus SVN Trunk, FPC 3.0 | 
CPU-Target: 64Bit
Nach oben

Beitragvon Mathias » 27. Jul 2017, 17:17 Re: Erfahrungsbericht/ Bug FormatSettings.DecimalSeparator

Deswegen habe ich da bisher immer alles auf '.' gestellt gehabt

Wen es immer ein '.' ist, dann kannst du das Ganze ohne Ländereinstellungen, etc, umgehen.

Nimm einfach Str und Val, da wird immer ein Punkt verlangt.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4351
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

• Themenende •

Zurück zu Lazarus - Bugs



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

porpoises-institution
accuracy-worried