Windows 10 and FormClose lazarus / 34-Windows ---------------------------------------------------------------------- rick2691 · 2019-06-24 16:17 I am using the following code for a very simple program. In WinXP it always worked, but not now in Win10. I have several other programs that are complicated, and they use similar or same code, but they work fine in Win10. I can't understand what is happening with this particular program. When closing the App under development it gives an assembler idiv error. If compiled, Windows gives a "divide by zero" error. There isn't anything that divides by zero, and again, it doesn't happen in WinXP. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);beginCloseAction:= caFree;(* // alternately for mechanical choice...if MessageDlg('Close application?', mtConfirmation, [mbYes, mbNo], 0) = mrYes   then CloseAction:= caFree   else CloseAction:= caMinimize;*)end; procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: boolean);var CfgFile: TextFile;    DatStr: string;    OK: boolean;  // DatOK: boolean;    IOval: integer;  // longint;beginAssignFile(CfgFile, PrgmFolder+'CmdRPN.cfg');{$I-} Rewrite(CfgFile) {$I+};IOval:=IOresult; OK:=(IOval=0);if OK then   // was DatOK   begin try         Str(Reg0,DatStr); Writeln(CfgFile,DatStr);  // register display       Str(Reg1,DatStr); Writeln(CfgFile,DatStr);         Str(Reg2,DatStr); Writeln(CfgFile,DatStr);         Str(Reg3,DatStr); Writeln(CfgFile,DatStr);         Str(Reg4,DatStr); Writeln(CfgFile,DatStr);          Str(Mem1,DatStr); Writeln(CfgFile,DatStr);  // storage memory         Str(Mem2,DatStr); Writeln(CfgFile,DatStr);         Str(Mem3,DatStr); Writeln(CfgFile,DatStr);         Str(Mem4,DatStr); Writeln(CfgFile,DatStr);         Str(Mem5,DatStr); Writeln(CfgFile,DatStr);         Str(Mem6,DatStr); Writeln(CfgFile,DatStr);         Str(Mem7,DatStr); Writeln(CfgFile,DatStr);         Str(Mem8,DatStr); Writeln(CfgFile,DatStr);         Str(Mem9,DatStr); Writeln(CfgFile,DatStr);          Str(Dsp,DatStr); Writeln(CfgFile,DatStr); // decimal display         if HrsMode=true then DatStr:='1'  // HmsMode ...Dms                         else DatStr:='0'; // HrsMode ...Dec         Writeln(CfgFile,DatStr); // angle mode          finally         Flush(CfgFile);         CloseFile(CfgFile);         CanClose:= true;          end;  // end try   end    else  begin         CloseFile(CfgFile);         CanClose:= false;         end;end; ---------------------------------------------------------------------- ASerge · 2019-06-24 17:44 With debugging information, you can get a stack trace to find the code that generates the error. ---------------------------------------------------------------------- rick2691 · 2019-06-25 12:05 Thanks ASerge, Assembler Error without debug: 00452FB2 f7f9      idiv   %ecx With debug active: raised exception class 'External: SIGFPE'. At address 452FB2 With backtrace active: In file 'lclproc.pas' at line 902 source://C:\Lazarus\fpc\3.0.2\source\rtl\win32\system.pp(16,1) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure RaiseGDBException(const Msg: string);  // *lclproc.pas*begin  debugln(rsERRORInLCL, Msg);  // creates an exception, that gdb catches:  debugln(rsCreatingGdbCatchableError);  DumpStack;  if (length(Msg) div (length(Msg) div 10000))=0 then ;   // *line 902*end; The first time that I used debug on this I did not get any error. I switched debug off and ran it, and it produced the former error. I switched debug on again, and it gave the above data. I don't know what to do with what I am looking at. I also have compiler version 2.0.2, and it gives this error also. ---------------------------------------------------------------------- rick2691 · 2019-06-25 12:30 I just went back to vers 2.0.2. Now it is not creating the error. I also activated debugging, and no error. Formerly, with the 1.6.4 version operating as compiled app, I was getting crash frequently but not always. ---------------------------------------------------------------------- marcov · 2019-06-25 12:46 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if (length(Msg) div (length(Msg) div 10000))=0 then ;   // *line 902*end; This goes wrong if length(msg) div 10000=0 Which is true for anything under 10000. So the code is simply wrong. Check your divisors for divide by zero. In some cases external libraries (including video card drivers via their opengl implementation, if you USE that) can toggle  the default state to ignore, but it remains incorrect. Keep in mind: Working code does NOT mean correct code, and it is pointless to linger on why incorrect code sometimes works and sometimes not. Just correct the code. ---------------------------------------------------------------------- rick2691 · 2019-06-25 13:03 Thanks Marcov, It only crashes when exiting the program. That is why I posted the exit handlers that I am using. There is no division at all. ---------------------------------------------------------------------- rvk · 2019-06-25 13:15 Quote from: marcov on June 25, 2019, 02:46:50 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if (length(Msg) div (length(Msg) div 10000))=0 then ;   // *line 902*end; This goes wrong if length(msg) div 10000=0 Which is true for anything under 10000. So the code is simply wrong. Check your divisors for divide by zero. No, the code is not wrong. The division by zero is very intentional. It's in RaiseGDBException where the code forces an exception because of something. The real code is in laztracer.pas (in components/lazutils) and reads like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure RaiseGDBException(const Msg: string);begin  DebugLn(lrsERRORInCode, Msg);  // creates an exception, that gdb catches:  DebugLn(lrsCreatingGdbCatchableError);  DumpStack;  {$ifndef HASAMIGA} // On Amiga Division by 0 is not catchable, just crash  if (length(Msg) div (length(Msg) div 10000))=0 then ;  {$endif}end; So nothing to do with an actual division by zero but just code to make it crash intentionally. But you are correct about working code does not mean correct code. There is still some error somewhere. Best way to find it is debugging and stepping through the code. Set some Showmessage at certain points and see if the code reaches it. Or use F5 to set breakpoints and use the debugger. If the program only crashes at the end you'll need to strip the code. For example strip the complete CloseQuery and see if it makes a difference. If not, strip some other code until you don't receive the error on exit. ---------------------------------------------------------------------- nanobit · 2019-06-26 09:47 Rick, you seem to be under win32, for better debugging with system exceptions (SIGFPE, ...) you can use win32Veh.pas from: https://forum.lazarus.freepascal.org/index.php/topic,44905.0.html ---------------------------------------------------------------------- Thaddy · 2019-06-26 10:27 Quote from: nanobit on June 26, 2019, 11:47:02 amRick, you seem to be under win32, I would be very, very surprised if that was the case. He's on many platforms and always takes the time to test. He's most certainly not on abandon ware. (win32) by default. Reasoning: in the Netherlands and Belgium Win32 is only available on special request or as a Microsoft certified developer with an MSDN subscription: There is not a distribution for Win32 *at all* apart from such request or an professional MSDN account. In the low lands Win10 = 64 bits, usually. Maybe you mean he is compiling for 32 bits? Which is supported in this last win 10.1 version but will be dropped from newer major Windows than 10. Just like Apple's OSX did. https://en.wikipedia.org/wiki/Up_to_eleven ---------------------------------------------------------------------- nanobit · 2019-06-26 10:35 Thaddy, I referred to rick2691, signature and his 2nd post: "With backtrace active: In file 'lclproc.pas' at line 902 source://C:\Lazarus\fpc\3.0.2\source\rtl\win32\system.pp(16,1)" But you know better.... ---------------------------------------------------------------------- rvk · 2019-06-26 10:36 Quote from: Thaddy on June 26, 2019, 12:27:32 pmReasoning: in the Netherlands and Belgium Win32 is only available on special request or as a Microsoft certified developer with an MSDN subscription: There is not a distribution for Win32 *at all* apart from such request or an professional MSDN account. In the low lands Win10 = 64 bits, usually. That doesn't mean development itself can't be in Win32 for Lazarus/FPC. In fact, looking at the signature of Rick, i386-win32 is still included in the mix. QuoteWindows 10, LAZ 1.6.4, FPC 3.0.2, SVN 54278, i386-win32-win32/win64, forms use windows unit Edit: Ah, and @nanobit also saw the source-code path (as win32). ---------------------------------------------------------------------- rvk · 2019-06-26 10:40 Quote from: Thaddy on June 26, 2019, 12:27:32 pmMaybe you mean he is compiling for 32 bits? Which is supported in this last win 10.1 version but will be dropped from newer major Windows than 10. Just like Apple's OSX did.Yikes, I wonder when that will be (actual date). I'm still under Delphi 32bit for my commercial program and wasn't planning on switching soon. ---------------------------------------------------------------------- Thaddy · 2019-06-26 10:41 still, my post has some value: win32 is 0.5% or less of the licenses (According to microsoft) and compiling for 32 bit windows is abandon ware. (or silly!) ---------------------------------------------------------------------- rvk · 2019-06-26 10:44 About 50% of my customers still run computers with 32bit OS versions on it (ranging from XP, few, to Windows 7 majority). Although Windows 7 might be out of support it's still used a lot. I guess I need to look into compiling and maintaining two versions then. ---------------------------------------------------------------------- Thaddy · 2019-06-26 10:44 Quote from: rvk on June 26, 2019, 12:40:13 pmQuote from: Thaddy on June 26, 2019, 12:27:32 pmMaybe you mean he is compiling for 32 bits? Which is supported in this last win 10.1 version but will be dropped from newer major Windows than 10. Just like Apple's OSX did.Yikes, I wonder when that will be (actual date). I'm still under Delphi 32bit for my commercial program and wasn't planning on switching soon. There was an announcement on the MSDN blogs and an accompanying email if you are subscribed. Will take some time, but the next major number release (11?) will be 64 bit only on Intel. Didn't you know that? BUT there is LTS support until 2024 for Windows 10. Btw, apologies for confusing Rik's with Rick's.... ---------------------------------------------------------------------- Thaddy · 2019-06-26 10:53 Quote from: rvk on June 26, 2019, 12:44:25 pm About 50% of my customers still run computers with 32bit OS versions on it (ranging from XP, few, to Windows 7 majority). Although Windows 7 might be out of support it's still used a lot. I guess I need to look into compiling and maintaining two versions then. WHY didn't they upgrade...? It was free (I don't know if it still is..) Government customers? Social sector? you know what I mean. XP is no longer supported except for - very expensive - special cases. Same goes for Win7 LTS support next year, 2020. Remember: you are the messenger, don't shoot the messenger.... As for two versions: No, make sure your codebase is bitness agnostic and don't use assembler (that's the niggle) ---------------------------------------------------------------------- Thaddy · 2019-06-26 11:04 I forgot to add windows 32 bit SERVER editions are already gone for a long time. If your customers use that, they have real issues. Gimme the links and I do - with permission - a QED,,, (this time for free)  ) I am CEH as you know. ---------------------------------------------------------------------- rvk · 2019-06-26 11:05 Some computers (workstations within companies) with XP that couldn't be upgraded. Some other people didn't upgrade to Win10 (reasons ranging from unknown to "didn't want to upgrade" or "didn't want to bother an administrator to do it"). These are companies with 0 to 5 employees (so small companies). I even have some customers on a DOS-version of our program (inside WinXP-Win7) although that version doesn't get any new development anymore. Luckily I'm not responsible for their network environment  Anyway, the program is mostly pure pascal so recompiling for Win64 should be relatively easy (changing the source code here and there). QuoteWHY didn't they upgrade...? It was free (I don't know if it still is..)Until last year you could still upgrade (under the assumption you used the disabled-features which wasn't checked). Don't know if that's still the case. ---------------------------------------------------------------------- rick2691 · 2019-06-26 12:49 @rvk QuoteBest way to find it is debugging and stepping through the code. Set some Showmessage at certain points and see if the code reaches it. Or use F5 to set breakpoints and use the debugger. If the program only crashes at the end you'll need to strip the code. For example strip the complete CloseQuery and see if it makes a difference. If not, strip some other code until you don't receive the error on exit. Thanks for the input. I try to track your way (sounds like tracking LISP). By posting I was hoping that someone else would have had a similar issue and a quicker fix. @others I am developing in both Win32 and 64 (vers 1.6.4 and 2.0.2). Both are having the same failure at closing the app. WinXP does not have the problem, so I expect that it is Win10 issue. Also, I have a dozen programs that don't have a closing error on either platform. So, yes, I am probably using a function or format with this program that is not supported anymore. It is an old program, so it might be the GUI interface. ---------------------------------------------------------------------- Thaddy · 2019-06-26 14:00 Microsoft has been way more strict with rights, so I expect that is the real issue , not the compiler, nor Lazarus. The only thing that got REALLY dropped by fpc is win95/98 support. Note that older versions of the compiler are still available w/o any modern features. I need a simple code example that reproduces the issue to pinpoint it to you. That's probably just reading it... ---------------------------------------------------------------------- Thaddy · 2019-06-26 14:08 Quote from: rvk on June 26, 2019, 01:05:55 pmLuckily I'm not responsible for their network environment  Actually, morally, you are.... Accidents waiting to happen and then they blame your software...... Be grumpy, you have my permission... ---------------------------------------------------------------------- ASerge · 2019-06-26 19:13 Quote from: rick2691 on June 25, 2019, 02:05:01 pmWith backtrace active: In file 'lclproc.pas' at line 902 source://C:\Lazarus\fpc\3.0.2\source\rtl\win32\system.pp(16,1) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure RaiseGDBException(const Msg: string);  // *lclproc.pas*begin  debugln(rsERRORInLCL, Msg);  // creates an exception, that gdb catches:  debugln(rsCreatingGdbCatchableError);  DumpStack;  if (length(Msg) div (length(Msg) div 10000))=0 then ;   // *line 902*end;  You should look at the stack trace earlier. This procedure is called to pass an error to the debugger, that is, an error has occurred before. ---------------------------------------------------------------------- metis · 2019-06-28 10:57 @rick2691 In Case of You use external Libs with Your App: - Did You ensure, that they close properly with Win10, too ? - Did You try out SetExceptionMask([exZeroDivide]); {math} ? With 'SetExceptionMask()' You obtain, what marcov meant with QuoteIn some cases external libraries (...) can toggle  the default state to ignore QuoteI was hoping that someone else would have had a similar issue and a quicker fixI don't have Problems with Closing, but with Resizing on Win10: (More precisely, the Following occurs with Win10 Home, but not with Win10 Pro) I wrote a FFmpeg-MediaPlayer with LCL (Laz v1.8.4 + FPC v3.0.4), that uses SDL (still SDL1) as VideoOutput (all Win32). Everything works perfectly on WinXP and Win7 32bit, but on Win10 I got one really insisting Problem: When the SDL-Window is captured (= internal Videoscreen), it can be resized inside of the PlayerForm, but Resizing the PlayerForm itself hangs after some Resizes. When the SDL-Window is released (= external Videoscreen), Resizing of both, the SDL-Window and the PlayerForm hangs after some Resizings. In both Cases, no Errors are shown. There is also a ConsoleVersion of the Player, where there are no ResizingProblems with the SDL1-Window. Really don't know, if it's because of Win10 or because of still Using SDL1 or because of my Code. -> No Idea, no Solution, no Fix yet to solve this Problem with the GUI on Win10.  => Question to all: What has changed particularly with Win10 resp. its API, that may cause Behaving the same App differently with Win10 ? ---------------------------------------------------------------------- rick2691 · 2019-07-01 18:07 @metis By excluding certain functions I am pretty sure that my problem is a "floating format" issue. The program is a calculator, so it also has trouble with the str(x:0:4) function. It appears that if "x" is nearly zero (ie. 1123E-240) it throws an exception. I tried the SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]) method. It did not help, although it was designed for this very reason. I also tried {+$SAFEFPUEXCEPTIONS}. It is also supposed to help with tracking the errors. But no help. At this point I do not believe that these things are due to my coding, and although I am hesitant to blame lazarus or freepascal, it does seem possible that their method for managing floating numerals is not completely compatible with Windows10. Since I have not found any remedy, however, I have to conclude that Windows10 has made the problem to begin with (due to some inane security protocol), because it does not occur with WindowsXP. ---------------------------------------------------------------------- mas steindorff · 2019-07-01 19:43 I jumped from 1.2 to 2.0 and had a similar "onclose" issue. I was not directly writing to file but was using a XMLPropStorage and saving a memo.  I found, for my "exception on close" when away when I unchecked the "use manifest resource" for windows option.  I can tell you why and I've tried to recreate the bug but it's gone away.  I was also playing around with 64 vis 32 bit Lazarus so I can not really say the manifest flag was the fix/issue but it's something quick you can try. ---------------------------------------------------------------------- ASerge · 2019-07-01 19:50 Quote from: rick2691 on July 01, 2019, 08:07:20 pmBy excluding certain functions I am pretty sure that my problem is a "floating format" issue. The program is a calculator, so it also has trouble with the str(x:0:4) function. It appears that if "x" is nearly zero (ie. 1123E-240) it throws an exception. You can make an example? On my machine the following code is executed without problems with x32 and x64: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$APPTYPE CONSOLE}{$IFDEF FPC} {$MODE OBJFPC} {$ENDIF}{$LONGSTRINGS ON} uses Math; var  X: ValReal = 1123;  S: string;begin  X := X * Power(10, -240);  Str(X:0:4, S);  Writeln(S);  Writeln(X);  Readln;end. ---------------------------------------------------------------------- rick2691 · 2019-07-02 10:07 @ASerge, notes are in the code. But I do not have {$APPTYPE CONSOLE} {$IFDEF FPC} {$MODE OBJFPC} {$ENDIF} {$LONGSTRINGS ON} in my code. I have {$mode objfpc}{$H+} interface uses   {$IFDEF WINDOWS}   win32proc,   {$ENDIF} ... implementation {$R *.lfm} ... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i //These are the global variables var  AppForm: TAppForm;  Reg0,Reg1,Reg2,Reg3,Reg4,Lst,Hrs,Hms: double; // reg0 is for swapping display stack  Mem1,Mem2,Mem3,Mem4,Mem5,Mem6,Mem7,Mem8,Mem9: double;  Err,Dsp: integer;  TmpStr,LstDsp,PrgmFolder: string;  NewReg,SavReg,StoActive,HrsMode: boolean;  //This is the function that creates an onclose crash.//If I exclude this call the program does not crash at OnClose.//Debug indicates that it is Str(Reg1:0:Dsp,TmpStr) ... it is as if Reg1 has junk data in it.//But I don't understand why UpdDsp is firing at OnClose to begin with. procedure TAppForm.UpdDsp;var x,z:integer;begintryStr(Reg1:0:Dsp,TmpStr); // *** crash point at OnClose ***x:= pos('.',TmpStr);z:= length(TmpStr);if (x>17)or(z>17) then  // this only fires when a number is very large ... large numbers are not the problem.   begin   TmpStr:= FloatToStrF(Reg1,ffExponent,17,0); //showmessage(TmpStr);   end;RegBox1.text:= TmpStr;finallyend; tryStr(Reg2:0:Dsp,TmpStr);x:= pos('.',TmpStr);z:= length(TmpStr);if (x>17)or(z>17) then   begin   TmpStr:= FloatToStrF(Reg2,ffExponent,17,0); //showmessage(TmpStr);   end;RegBox2.text:= TmpStr;finallyend; tryStr(Reg3:0:Dsp,TmpStr);x:= pos('.',TmpStr);z:= length(TmpStr);if (x>17)or(z>17) then   begin   TmpStr:= FloatToStrF(Reg3,ffExponent,17,0); //showmessage(TmpStr);   end;RegBox3.text:= TmpStr;finallyend; tryStr(Reg4:0:Dsp,TmpStr);x:= pos('.',TmpStr);z:= length(TmpStr);if (x>17)or(z>17) then   begin   TmpStr:= FloatToStrF(Reg4,ffExponent,17,0); //showmessage(TmpStr);   end;RegBox4.text:= TmpStr;finallyend;ResetFocus;Update;end;  //I use this exception handler which writes to a log file.//It does not activate at OnClose, so the crash is not the program.//Yet debug is indicating that the crash is on account of Str(Reg1:0:Dsp,TmpStr).//It is as if there are some trashed functions or variables that are not being purged at OnClose. procedure TAppForm.LogException(Sender: TObject; E: Exception);var ErrorFile: TextFile;    ErrorInfo: String;    AppPath,SenderMsg: string;beginSenderMsg:= E.Message;  // e.message contains line-feedAppPath:= ExtractFilePath(ParamStr(0));AssignFile(ErrorFile, AppPath+'CmdRPN.log');if FileExists(AppPath+'CmdRPN.log')   then Append(ErrorFile)   else Rewrite(ErrorFile);ErrorInfo:= DateTimeToStr(Now)+' Unhandled exception';if Assigned(Sender)   then ErrorInfo:= ErrorInfo+' in '+Sender.UnitName+'->'+Sender.ClassName;ErrorInfo:= ErrorInfo+': '+SenderMsg;try WriteLn(ErrorFile, ErrorInfo);    finally    CloseFile(ErrorFile);    ShowMessage('Application fault... message saved: CmdRPN.log');    end;end; //These are the Close functions that I employ ... there is no call to UpdDsp in them. procedure TAppForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);beginCloseAction:= caFree;end; procedure TAppForm.FormCloseQuery(Sender: TObject; var CanClose: boolean);var CfgFile: TextFile;    DatStr: string;    OK: boolean;  // DatOK: boolean;    IOval: integer;  // longint;beginAssignFile(CfgFile, PrgmFolder+'CmdRPN.cfg');{$I-} Rewrite(CfgFile) {$I+};IOval:=IOresult; OK:=(IOval=0);if OK then   // was DatOK   begin try         Str(Reg0,DatStr); Writeln(CfgFile,DatStr);  // register display       Str(Reg1,DatStr); Writeln(CfgFile,DatStr);         Str(Reg2,DatStr); Writeln(CfgFile,DatStr);         Str(Reg3,DatStr); Writeln(CfgFile,DatStr);         Str(Reg4,DatStr); Writeln(CfgFile,DatStr);         Str(Mem1,DatStr); Writeln(CfgFile,DatStr);  // storage memory         Str(Mem2,DatStr); Writeln(CfgFile,DatStr);         Str(Mem3,DatStr); Writeln(CfgFile,DatStr);         Str(Mem4,DatStr); Writeln(CfgFile,DatStr);         Str(Mem5,DatStr); Writeln(CfgFile,DatStr);         Str(Mem6,DatStr); Writeln(CfgFile,DatStr);         Str(Mem7,DatStr); Writeln(CfgFile,DatStr);         Str(Mem8,DatStr); Writeln(CfgFile,DatStr);         Str(Mem9,DatStr); Writeln(CfgFile,DatStr);         Str(Dsp,DatStr); Writeln(CfgFile,DatStr); // decimal display         if HrsMode=true then DatStr:='1'  // HmsMode ...Dms                         else DatStr:='0'; // HrsMode ...Dec         Writeln(CfgFile,DatStr); // angle mode         finally         Flush(CfgFile);         CloseFile(CfgFile);         CanClose:= true; //showmessage('closing by CanClose');  // good         end;  // end try   end else begin          CloseFile(CfgFile);            CanClose:= false;            end;CanClose:= true; //showmessage('closing by CloseQuery');  // goodend; ---------------------------------------------------------------------- wp · 2019-07-02 10:29 Code snippets like these are not very helpful unless the issue is very straightforward. If someone wants to use your code to reproduce or study the error he still has a lot to add by himself for which there are numeous possibilities. Better to post a compilable project. The main effect is for yourself because it forces you to remove everything not needed, and this quite often gives you an idea of what causes the issue. Not your problem, but: - Use global variables only when absolutely necessary. TmpStr, for example, is needed only locally with several routines. Declare it locally. - Why are you using empty finally blocks in try-finally-end? This is absolutely useless. ---------------------------------------------------------------------- rick2691 · 2019-07-02 11:53 @wp QuoteWhy are you using empty finally blocks in try-finally-end? This is absolutely useless.Because the editor automatically kicks the 'finally' in. I leave them because I might need them later. They do any harm. QuoteCode snippets like these are not very helpful I have posted the code because ASerge asked me to. @ASerge The crash does not need a large number to crash. I can add 55 and 22 together, and it crashes when I hit the close button at the top of the form. Nevertheless, debug reports that Str() has tried to convert a large number. ---------------------------------------------------------------------- wp · 2019-07-02 12:53 Quote from: rick2691 on July 02, 2019, 01:53:39 pmQuoteCode snippets like these are not very helpful I have posted the code because ASerge asked me to. I am asking for it, too. Having no compilable code often leads to endless discussions because everybody does and understands things a bit different. ---------------------------------------------------------------------- howardpc · 2019-07-02 14:16 Quote from: rick2691 on July 02, 2019, 01:53:39 pm@wp QuoteWhy are you using empty finally blocks in try-finally-end? This is absolutely useless.Because the editor automatically kicks the 'finally' in. I leave them because I might need them later. They do any harm. The editor adds finally only if you introduce "try" yourself. Such redundant blocks will harm performance-critical sections of code unnecessarily. There is a small speed penalty introduced with each "try" block. ---------------------------------------------------------------------- rick2691 · 2019-07-02 18:57 @howardpc I did not have the 'try' implemented earlier. I added it because debug was saying that the crash was on Str() and it choked on value that was too large or small. After implementing the 'try' it did not change the event. The math was with normal numbers ... 22, 55, 66 etc. The math processed correctly. Only when I closed the program had the crash occurred. The application disappeared and the exception notice popped up. I also notice that it usually happens when I have used the keyboard to enter values. I have numeral buttons on the GUI. If I use them I don't get a crash. ======================== These are typical for the GUI entry... procedure TAppForm.Num2BtnClick(Sender: TObject); begin ChkReg; RegBox1.Text:= RegBox1.Text+'2'; ResetFocus; end; procedure TAppForm.PlusBtnClick(Sender: TObject); begin Lst:=Reg1; Reg1:=Reg1+Reg2; Reg2:=Reg3; Reg3:=Reg4; Reg4:=0; UpdDsp; NewReg:=true; SavReg:=true; end; ========================== These are typical for keyboard entries... procedure TAppForm.RegBox1KeyPress(Sender: TObject; var Key: Char); var KeyOK:boolean;     x:integer; begin KeyOK:=false; if (Key in ['0'..'9'])or(key='.') then  //digit keys    begin    KeyOK:=true; ChkReg; //PutKey(Key);    RegBox1.Text:= RegBox1.Text+Key;    X:=Pos('.',RegBox1.Text);    if x=1 then RegBox1.Text:= '0'+RegBox1.Text;    ResetFocus; Key:=#0;    end; if Key=#13 then   //enter key    begin    if RegBox1.Text='' then RegBox1.Text:='0';    Lst:=Reg1;    KeyOK:=true; UpdReg; UpdDsp; NewReg:=true; SavReg:=false; Key:=#0;    end; if Key='+' then   //plus key    begin    Lst:=Reg1;    Reg1:=Reg1+Reg2; Reg2:=Reg3; Reg3:=Reg4; Reg4:=0; Key:=#0;    KeyOK:=true; UpdDsp; NewReg:=true; SavReg:=true;    end; if Key='-' then    //minus key    begin    Lst:=Reg1;    Reg1:=Reg2-Reg1; Reg2:=Reg3; Reg3:=Reg4; Reg4:=0; Key:=#0;    KeyOK:=true; UpdDsp; NewReg:=true; SavReg:=true;    end; ======================== It is all simple stuff. It has the capacity to generate numbers that are too large, but my exception trap catches them. It doesn't crash by those operations. Everything looks good. It only crashes when closing the application, and it has nothing to do with large numbers, though debugging is saying that it does ... with 2+2=4, and they were entered by the keyboard. Both buttons and keyboard are using the UpdDsp (update display) function. If you think that I must, I can upload the entire project. It's just a calculator. ---------------------------------------------------------------------- ASerge · 2019-07-03 17:22 Quote from: wp on July 02, 2019, 02:53:04 pmQuote from: rick2691 on July 02, 2019, 01:53:39 pmQuoteCode snippets like these are not very helpful I have posted the code because ASerge asked me to. I am asking for it, too. Having no compilable code often leads to endless discussions because everybody does and understands things a bit different. +1. With this piece of code the error does not reproduce. ---------------------------------------------------------------------- metis · 2019-07-04 11:01 @rick2691 QuoteI tried the SetExceptionMask...It did not helpYou must put it at the very Beginning of the Program - Did You do so ? QuoteThe program is a calculator + I do not believe that these things are due to my codingI found a Calculator (normal-scientific-graphic) in my DelphiCode-Collection (see attached 'Calculator.7z'). Though I never tried it out, maybe it's helpful for Your App, maybe this Code also behaves strange on Win10. QuoteIt only crashes when closing the applicationDid You try out the HeapTrc-Unit (-gh Switch) to check Memory-Allocation/Deallocation ? ---------------------------------------------------------------------- rick2691 · 2019-07-04 15:25 It is really difficult to send an attachment. It has posted as an another thread with the same title. ---------------------------------------------------------------------- metis · 2019-07-04 16:42 @rick2691 QuoteIt has posted as an another thread with the same titleHope, You agree, that I copied Your Post from the other Thread over here to keep continuity: (So, my previous Post served as a placeholder)  ********************************************************************** ***************** @metis HeapTrc-Unit (-gh Switch): memory blocks allocated and freed equal each other unfreed memory blocks equal zero true heap = 229376 true free heap = 229248 true free heap should = 229376 ==== SetExceptionMask: I did not put it at the start. I put it at the start of FormCreate. Calculator.7z: He uses a different approach but it looks essentially the same by my review. ================= attached: Laz-CmdRPN - Copy.zip This is the entire project. It is 32bit. It is a scientific RPN (reverse-polish-notation) calculator. Entry example: 32 enter 20 plus ... the result is 52. ********************************************************************** ***************** ---------------------------------------------------------------------- wp · 2019-07-04 17:02 I compiled and ran the program posted in the other thread (https://forum.lazarus.freepascal.org/index.php/topic,45983.msg325974) - no issue, no crash when I close the program. What exactly do I have to do to reproduce the error? I do: - click '5', '5'   (--> displays '55') - click 'ENTER'  (--> displays '55.00') - click '2', '2'   (--> displays '22') - click '+' (--> displays '77.00') - click close-x in the title bar of the form --> program closes without an error (there is a heaptrc message, but this is expected). OS: Win 10, 64 bit (v1903) Laz trunk / fpc 3.0.4  / 32 bit, or Laz 1.6.4 / fpc 3.0.2 / 32 bit ---------------------------------------------------------------------- rick2691 · 2019-07-04 18:45 I always type enough digits to allow for a / * - and +, but I do it all from the keyboard. If it isn't showing, I do it again and also do a Sqr, SqRt, Sin and ASine. Always closing by the CloseButton at the top of the form. ---------------------------------------------------------------------- rick2691 · 2019-07-04 21:43 @wp You also need to launch from an exe. If you do it by run, it is protected. ---------------------------------------------------------------------- wp · 2019-07-05 11:46 Still cannot reproduce... When scanning your code I saw these things which are unusual. I think, however, that they do not cause your issues: Unit "win32proc" normally is not needed in an LCL program. I can remove it without any issuesFormClose: Assigning caFree to CloseAction seems to be redundant because the main form of an application is automatically destroyed when it is closed. I can remove this line without negative effect.Like many others, you use the form's name in the code of the class. This is badly wrong because it makes your program fail when you'll once decide to rename the form instance or to require another differently named instance of that class. Just remove "AppForm." in all TAppForm methods. If there should be a naming conflict with other identifiers use "self." instead. ---------------------------------------------------------------------- rick2691 · 2019-07-06 17:10 I took out Win32Proc. It had a minor improvement. This is with a Win8 compatibility, and the highest security level that I could invoke. The mathematics did not crash it, but it I left it running and  ran other programs, upon returning and closing it, it crashed as before. I compiled it again as a WinXP compatibility, by placing it in another folder, it returned to the mathematics crash at closing. So I presume it is securities and compatibility that is creating the problem. Any ideas on how to overcome this? ---------------------------------------------------------------------- rick2691 · 2019-07-06 17:26 Technically I wouldn't call it a crash. It does everything that is supposed to be done. All the registries are are saved. It is more like an interrupt that hangs on after the destroy sequence. Its message is ... An unhandled exception occurred at $0040F338: $0040F338 ---------------------------------------------------------------------- ASerge · 2019-07-06 22:41 I sometimes get an error when I quickly perform several actions and exit the program (by Alt+F4 in Windows 10 and in Windows 7). Error occurs in the releasing a dynamic string in the units finalization. Occurs only for a 32-bit application. 64-bit works without failures. Try to get rid of global string variables. ---------------------------------------------------------------------- Cyrax · 2019-07-06 23:27 32-bit Windows programs needs SEH exception handling. FPC 3.0.4 doesn't support this. FPC 3.2.x (fixes) and trunk have support for this but you need to compile them with -dTEST_WIN32_SEH option. ---------------------------------------------------------------------- rick2691 · 2019-07-07 16:11 @ASerge I have a dozen other programs that are Win32, very much larger, more complex, many more globals, and they do not have this exception issue. Why is that? ---------------------------------------------------------------------- rick2691 · 2019-07-07 16:20 @Cyrex Can you be more specific about the trunk etc. What is its Web address? Is it many installs? What are their names. Where do you assign your script to effect your features? ---------------------------------------------------------------------- Cyrax · 2019-07-08 06:42 Quote from: rick2691 on July 07, 2019, 06:20:11 pm@Cyrex Can you be more specific about the trunk etc. What is its Web address? Is it many installs? What are their names. Where do you assign your script to effect your features? It might be easiest to get fpcupdeluxe and build the FPC trunk with it :  https://wiki.lazarus.freepascal.org/fpcupdeluxe ---------------------------------------------------------------------- rick2691 · 2019-07-08 12:55 I am going to hold off on going the fpcupdeluxe route at this point. Since I am operating on Win10 and have the 2.0.2 compiler, what are the proper settings for compiling for 32 bit and 64 bit applications? At present my Target settings are at Default, and I have assumed that would be a 64 bit app. I have also been using the Default setting with the 1.6.4 compiler, and I was assuming that was doing 32 bit apps. With both they use the Win32 widgetset. There is no widgetset for Win64. ---------------------------------------------------------------------- rvk · 2019-07-09 07:34 Quote from: rick2691 on July 04, 2019, 11:43:12 pmYou also need to launch from an exe. If you do it by run, it is protected. If you use Run, the program is launched from an exe. The Lazarus IDE (lazarus.exe). So I don't understand why none of us can reproduce this error. From what .exe are you launching this to get te error? Are you also getting the error if you just execute the program from the Windows explorer? ---------------------------------------------------------------------- rick2691 · 2019-07-09 10:54 @rvk Run is a protective environment. You have to compile the program as a stand alone exe. I always move it to a new folder, and activate it from there. The program disappears from the screen, and an Unhandled Exception message appears. If you look at the Windows Task Manager you will see that the program has not been destroyed. It is destroyed after you press OK. Sometimes there can be many Unhandled Exception messages that show up at the same time. I just go to the Windows Task Manager and end the task for the program. Otherwise you can spend 5 or 10 minutes clicking OK's. As requested earlier, I would like to know if I have the correct settings for my Compiler Options. I am using the Default settings, but I have Debugging turned off, as it would be if I gave the program to someone else. To date, Debugging has not helped me. ---------------------------------------------------------------------- rvk · 2019-07-09 11:07 Still not getting the error. Just newly installed Laz202 32bit in a separate dir with c:\laz202\config as config directory. So with all the default settings, just opened your example and pressed Shift+F9 to compile and run the .exe outside the IDE. Do you have any virusscanner active (other than Windows Defender) ? Could you disable it temporarily? ---------------------------------------------------------------------- rick2691 · 2019-07-09 11:53 @rvk Yes, I use "McAfee LiveSafe," and Windows Defender is disabled. I will try by disabling McAfee later. For now I have discovered something promising. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TAppForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);//begin//CloseAction:= caFree; var  i: Integer;  C: TComponent;begin  for i := ComponentCount - 1 downto 0 do  begin    C := Components[i];    if C is TCustomForm then    begin      //writeln('Component[',i,'] is  Form: ',C.ClassName,':',C.Name);      FreeAndNil(C);    end;  end;end; I changed the above Close method to a code that is posted elsewhere on the forum. With no incompatibilities set, it raised an exception the same as before. When I set Win8 compatibility, it has not raised any exceptions ... for several attempts with testing. At present I am going to just wait and  see. ---------------------------------------------------------------------- rvk · 2019-07-09 12:01 You shouldn't need to FreeAndNil() all those components on the form. The owner is TAppForm itself so they will be destroyed when the form itself is destroyed. And in fact... the FreeAndNil() is never executed because you check for "is TCustomForm". And you have no TCustomForm's in the Components of that form. Try setting a breakpoint with F5 on line 15 and see that it's never executed. Also, setting WinXP and Win8 compatibility shouldn't be need either. Doing so will only complicate your issue because that shouldn't be the cause. For now, my guess is McAfee. In fact, disabling the virusscanner should have been the first item on your list to try when having explainable issues with an OS. Quote from: rick2691 on July 09, 2019, 01:53:24 pmI changed the above Close method to a code that is posted elsewhere on the forum. With no incompatibilities set, it raised an exception the same as before. When I set Win8 compatibility, it has not raised any exceptions ... for several attempts with testing. At present I am going to just wait and  see. In fact, this makes my suspicions only bigger. Because your FormClose-changes actually do nothing, the only thing that made the difference would be setting that Win8 compatibility. And that could affect the McAfee virusscanner too. But you don't want to do that every time. So, first try to set everything back to normal (normal compat and normal options in Lazarus) and disable the virusscanner (temporarily). ---------------------------------------------------------------------- rick2691 · 2019-07-09 14:55 @rvk Most of what you say is true. I had not implemented beforehand on account of the same thought. Nevertheless, I have been rigorously trying to get a fail, and it has not happened. I believe there is a slight flaw in how the IDE is destroying the form. By slight I mean that it happens here, and some have confirmed that it happens with them but for different reasons. It is some sort of floating garbage. It should be analyzed by the engineers. But I have appealed to them about other cases in the past. I do not intend to do so again. ---------------------------------------------------------------------- rvk · 2019-07-09 15:04 Quote from: rick2691 on July 09, 2019, 04:55:24 pmI believe there is a slight flaw in how the IDE is destroying the form. By slight I mean that it happens here, and some have confirmed that it happens with them but for different reasons.The IDE isn't in question because you say it also happens when you run it outside the IDE (as release version). If it's something from Lazarus it would be the LCL-code itself. You might want to gather information about the other computers which give the error. Do they all run McAfee? Did you try to disable it yet? Could you run your .exe in a virtual machine (or another clean machine without any other software or virusscanner). The latest Windows 10 version has a Sandbox function which is a very clean Windows version onto itself. If the program runs fine there it must be something with your configuration (and still my best bet is the virusscanner as I have experienced 99% of the time). QuoteIt is some sort of floating garbage. It should be analyzed by the engineers. But I have appealed to them about other cases in the past. I do not intend to do so again.It can only be analysed when they can reproduce the error. That's the whole problem. You (with some of your other clients) are the only ones with this problem. We would be very (and I mean very very) happy to diagnose this problem if we could only reproduce it. ---------------------------------------------------------------------- ASerge · 2019-07-09 16:05 Quote from: rvk on July 09, 2019, 05:04:02 pmIt can only be analysed when they can reproduce the error. That's the whole problem. You (with some of your other clients) are the only ones with this problem. We would be very (and I mean very very) happy to diagnose this problem if we could only reproduce it. I was also able to reproduce the error. Rarely, after a series of operations (in the program), and closing, performed quickly and on the keyboard. The error is the same as rick2691 pointed out. Here are my stats: reproduce on Windows 7, Windows 10, on a physical computer, and in VirtualBox. With built-in Windows defender, with other antivirus (not listed above). Only in the 32-bit version (program). Tested only on 64-bit version of Windows. ---------------------------------------------------------------------- rvk · 2019-07-09 19:23 Quote from: ASerge on July 09, 2019, 06:05:14 pmI was also able to reproduce the error. Rarely, after a series of operations (in the program), and closing, performed quickly and on the keyboard.Could you elaborate as to the sequence? What keystrokes, fast after each other, could cause the direct error? And was the error after closing, directly after input or also after some idle time and then closing? How fast is your system? Could that be a factor? (slower machine so not everything is handled yet) (I'll try tomorrow again on a slower system) ---------------------------------------------------------------------- wp · 2019-07-09 19:58 Quote from: rick2691 on July 09, 2019, 01:53:24 pmFor now I have discovered something promising. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TAppForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);//begin//CloseAction:= caFree; var  i: Integer;  C: TComponent;begin  for i := ComponentCount - 1 downto 0 do  begin    C := Components[i];    if C is TCustomForm then    begin      //writeln('Component[',i,'] is  Form: ',C.ClassName,':',C.Name);      FreeAndNil(C);    end;  end;end; Why do you do this? This is not needed. All these controls were created with an "Owner" (the form), and the owner takes care of destroying them. Normally it works correctly, but beginning to destroy components yourself at the moment when the form is about to do the same sounds like calling for trouble. Normally, the main form normally does not need an OnClose handler at all. ---------------------------------------------------------------------- rvk · 2019-07-09 20:02 Quote from: wp on July 09, 2019, 09:58:49 pmWhy do you do this? This is not needed. All these controls were created with an "Owner" (the form), and the owner takes care of destroying them. Normally it works correctly, but beginning to destroy components yourself at the moment when the form is about to do the same sounds like calling for trouble. Normally, the main form normally does not need an OnClose handler at all. Yeah, that's what I also already said. And what's even more... It really doesn't do anything because none of the components which are owned, are TCustomForm. So this code really doesn't do anything. It just confused the whole issue and code. ---------------------------------------------------------------------- wp · 2019-07-09 20:23 I now found now a way to reproduce an error ("Externeal SIGSEV") when the program closes: - Run - Type "1" - Press "ENTER" - Type "2" - Type "+" - Type "+" - Close with "x" button or "F4" Error happens only with keyboard entry, not with clicked buttons. Speed of data entry is not important. I tested various Laz/FPC combinations on Win 10/64 bit: - Laz trunk / fpc 3.0.4 (32 bit) --> ERROR - Laz trunk / fpc trunk (32 bit)  ---> NO ERROR - Laz 2.0 / fpc 3.2-beta (32 bit) --> NO ERROR - Laz 1.8.4 / fpc 3.0.4 (32 bit) --> ERROR - Laz 1.6.4 / fpc 2.6.4 (32 bit) --> NO ERROR - Laz 1.8.4 / fpc 3.0.4 (64 bit) --> ERROR - Laz 2.0.2 / fpc 3.0.4 (64 bit) --> NO ERROR - Laz 2.0.2 / fpc 3.0.4 (32 bit) --> ERROR It almost looks as if the 32-bit compiler of fpc 3.0.4 has an issue. ---------------------------------------------------------------------- rvk · 2019-07-09 21:01 Quote from: wp on July 09, 2019, 10:23:49 pmIt almost looks as if the 32-bit compiler of fpc 3.0.4 has an issue. But you say Laz 1.8.4 64 bit also gives an error or is that a type/switch? (I still couldn't reproduce with laz202/32b on win10/64b) Edit: Ah, now I can after removing the heaptrc. Also inside the IDE with debugging on. I removed everything that had to do with saving and loading the .cfg and the error went away. It probably has something to do with the {$I} and IOResult. Edit #2: I also removed the scaling stuff //ScaleDPI(Self,ResizeInt); and the win32proc in the uses which isn't needed. ---------------------------------------------------------------------- wp · 2019-07-09 21:12 Quote from: rvk on July 09, 2019, 11:01:22 pmQuote from: wp on July 09, 2019, 10:23:49 pmIt almost looks as if the 32-bit compiler of fpc 3.0.4 has an issue. But you say Laz 1.8.4 64 bit also gives an error or is that a type/switch? Right. Seems that I missed this one. This brings the compiler out of focus - which agrees with my experience that almost 100% of the bugs are caused by user code, not by the compiler. ---------------------------------------------------------------------- rvk · 2019-07-09 21:31 It only happens for me when you have no .cfg file. I noticed that without it, 1 2 + + the second + doesn't do anything. With a .cfg file the second + adds 2. There is also a CloseFile(CfgFile); in CloseForm that gets executed when Rewrite() fails (which isn't correct). Also this urks me: {$I-} Rewrite(CfgFile) {$I+}; I would prefer to put the {$I+} after the ; {$I-} Rewrite(CfgFile); {$I+} Ctrl+D should be done to put all the indentations correct. Removing all the .cfg stuff I can persistently reproduce the error. And as I now can see the problem (I think) lies in ScaleDPI(Self, ResizeInt); Commenting it out removes the error at that point. ---------------------------------------------------------------------- wp · 2019-07-09 21:40 Yes, you are at the same point as myself. When I exit the ScaleDPI after the "with Control" block (before "if Control is TWinControl") the bug is already there. Strange... Simple MulDiv involved, and the numbers look reasonable (except for the FromDPI which is 91 - but this should not crash the program). ---------------------------------------------------------------------- rvk · 2019-07-09 21:43 The problem are in these lines (and the recursion of all the children). Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     with Control do    begin      Left := ScaleX(Left, FromDPI);      Top := ScaleY(Top, FromDPI);      Width := ScaleX(Width, FromDPI);      Height := ScaleY(Height, FromDPI);    end;Somehow, one of the children might be mistakenly be tagged as TWinControl and might get property Left/Top overwritten which could cause the crash. Commenting these out will erase the error. The problem is somewhere around there. It's late here so I'm going to call it a day. If it's nog solved tomorrow I will have a closer look. Edit: It's not even in the recursion. Commenting out the // ScaleDPI( inside the ScaleDPI, the error still occurs. So it's the assigning of Left/Top etc to the Form itself. Putting an exit; right after the with Control etc. confirms that. Putting an exit before the with Control, the error stays away. ---------------------------------------------------------------------- wp · 2019-07-09 22:12 Just replaced the ScaleX and ScaleY by Ondrej's Scale96ToFont or Scale96ToForm and the error is gone, although it does exactly the same, just with different variables. Hmmm... the third parameter in Scale96ToF* is "96" and when I explicitely call Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     Left := MulDiv(Left, 96, 96);    Top := MulDiv(Top, 96, 96);    Width := MulDiv(Width, 96, 96);    Height := MulDiv(Height, 96, 96); everything is ok, but when the third parameter is different from 96 (so that MulDiv really has something to do) the error is back... Do we have a bug in MulDiv? But MulDiv look harmless: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function MathRound(AValue: ValReal): Int64; inline;begin  if AValue >= 0 then  Result := Trunc(AValue + 0.5)  else    Result := Trunc(AValue - 0.5);end; function MulDiv(nNumber, nNumerator, nDenominator: Integer): Integer;begin  if nDenominator = 0 then    Result := -1  else  if nNumerator = nDenominator then    Result := nNumber  else    Result := MathRound(int64(nNumber) * int64(nNumerator) / nDenominator);end; Got the feeling the bug is somewhere else... ---------------------------------------------------------------------- rvk · 2019-07-09 22:16 I was wondering if maybe the cast of TForm to TControl could be the cause? (Can't test it now) Maybe Left and Top etc are redefined in a different place for TForm. But when I followed the source of Self.Top (with ctrl+up) I was taken to TControl.Left so that couldn't be it. ---------------------------------------------------------------------- wp · 2019-07-09 22:21 Quote from: rvk on July 09, 2019, 11:43:58 pmSo it's the assigning of Left/Top etc to the Form itself. Putting an exit; right after the with Control etc. confirms that. Putting an exit before the with Control, the error stays away. Ah! Writing "Left := Left + 1" already produces the error, forget about the MulDiv crap that I wrote... Calling SetBounds instead of setting Left, Top, Width and Height separately fixes the issue: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     SetBounds(      ScaleX(Left, FromDPI),      ScaleY(Top, FromDPI),    ScaleX(Width, FromDPI),      ScaleY(Height, FromDPI)    ); I think I read somewhere that this is the way control position and size should be set. I don't understand the details, it's too complicated for me. But I never had problems not doing it this way, but of course, it is true that setting Left, Top, Width and Height alone causes a lot of activity, in particular when this is done recursively. ---------------------------------------------------------------------- wp · 2019-07-10 07:37 Now I reloaded the original project, unchecked the heaptrc, commented the ScaleDPI call -> bug is back. Frustrating... ---------------------------------------------------------------------- rvk · 2019-07-10 08:20 Quote from: wp on July 10, 2019, 09:37:38 amNow I reloaded the original project, unchecked the heaptrc, commented the ScaleDPI call -> bug is back. Frustrating... Not for me. I reload the original, uncheck heaprtc, comment ScaleDPI and remove .cfg. No error. I uncomment ScaleDPI and remove .cfg Error. I'm going to see if I can strip down the complete project still containing the error. ---------------------------------------------------------------------- rvk · 2019-07-10 08:32 Commenting out TAppForm.UpdDsp also seems to help. I have a feeling there is some memory overwrite when some numbers are entered resulting in a corrupt TForm instance. ---------------------------------------------------------------------- rvk · 2019-07-10 09:41 Just for the other eyes... a (really) stripped down version. Just pressing 1 is enough to get the error (don't mind the display output). FYI. This is called stripping a project (compared to the original)  Edit: version 2 even more stripped down. Seems like it's somewhere in val() or str(). Also commenting out something like the empty if TmpStr <> RegBox1.Text then also fixes it. Really strange. ---------------------------------------------------------------------- rvk · 2019-07-10 10:48 Okay, reproducible with clean empty project. Project > New Project > ApplicationDouble click to create FormcreatePaste in Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Reg1 := 0.0;Paste the following under the global Form1: TForm1; variableCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   Reg1: double;  TmpStr: string;Drop a new TEdit on the formDouble click the events (in Inspector) OnChange and OnKeyPressPaste in the following in OnChangeCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   Str(Reg1: 0: 2, TmpStr);  if Edit1.Text <> 'a' then  begin    // the above if line causes error when exiting program  end; Paste in the following in OnKeyPressCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   if (Key in ['0'..'9']) or (key = '.') then  //digit keys  begin    Edit1.Text := Key;    Key := #0;  end;  if Key = #13 then   //enter key  begin  Key := #0;    Str(Reg1: 0: 2, TmpStr);    Edit1.Text := TmpStr;  end;Run the application (F9)Press 1 ERRORIf the error doesn't show up, change the Text property of the TEdit in the object inspectorRun the application (F9)Press 1 ERROR For me this is reproducible. But I'm not sure what is actually causing the error. Commenting the if Edit1.Text <> 'a' then line makes the error go away (which is nuts). Doing 1 2 also doesn't show the error. Makes me wonder is Str() doesn't overwrite any unreserved memory for TmpStr. Making TmpStr a array[0..1000] of char fixes it too (in both the clean example and original). Making TmpStr local variable also fixes it. ASerge already warned for the global variable but it seems that a global string variable in combination with str() does create the crash. ---------------------------------------------------------------------- wp · 2019-07-10 16:29 Great work. I made all TmpStr of the original demo local variables, and the error is gone, even with ScaleDPI active. In your 2nd stripped down demo I replaced the "str(Reg1:0:Dsp, TmpStr)" by "str(Reg1, TmpStr") and the error is gone (even with the global TmpStr). I made the global TmpStr to a type String[255], and the error is gone. It really looks as if something is wrong with the str() procedure in combination with global strings. Unfortunately the called routines in flt_core.inc and flt_conv.inc (in rtl/inc) are not easily understood... ---------------------------------------------------------------------- rvk · 2019-07-10 17:09 Yes. Somehow that str(x:0:2, temp) stuffs too much characters in temp without reserving the space with setlength. Not sure how to make a simple example which shows that problem clearly. ---------------------------------------------------------------------- nanobit · 2019-07-10 20:13 I made a quick test, but I have no fpc debug version. str(f:w:d, s) creates severe memory corruptions, in fpc 3.0.4 and fpc 3.2. I tested with f := 0.001 (and others), (w = 0..7), (d = 3), all combinations buggy. The effect: Crashes later at different places in apps: at other (unrelated) string expressions in other routines. The more string expressions in the app, the more likely a crash (at a string expression). str() is using fpc_ansistr_float. It's a huge bug. Typical errors: SIGSEGV, SIGILL (not SIGKILL), ERangeError (by fpc_ansistr_rangecheck) Heaptrc memory manager has no impact: Is either used or unused (if environmentvar: HEAPTRC = "disabled") Update: Cannot reproduce crash with current FPC trunk: I use same project setting, same Lazarus 2.0.2 (but rebuilt with FPC trunk), and project shows no crash. Don't know the reason, maybe it's solved or not. With FPC trunk, the rvk example behaves different too: no crash. Last update: Since a day I cannot reproduce my reported crash. My current assumption is: This was the sideeffect of an invalid breakpoint. Which means, we have no different test project now. ---------------------------------------------------------------------- wp · 2019-07-10 21:42 Can you post a simple non-lcl demo to demonstate the issue to the compiler people? ---------------------------------------------------------------------- nanobit · 2019-07-11 06:56 Quote from: wp on July 10, 2019, 11:42:08 pmCan you post a simple non- lcl demo to demonstate the issue to the compiler people? Such test project is probably not possible within days, because in the exe file, every compiled line before str() has impact on the occurrence of crash and I cannot publish my source. On every source change (exclude any unit, or any sourceline) the crash effect changes (mostly disappears). But I know for sure, the bug is not LCL: The normal LCL unit files are initialized in uses clause, but nothing else of LCL is called before the crash, my project unit is: begin   someUnit.doCrashTest; // crashes occur here (after calling str(f:w:d, s) in there)   exit; // always exit here   // unused, but can't be removed (changes exe file, thus removes crash above)   Application.Scaled:=True;   Application.Initialize;   Application.CreateForm(TForm1, Form1);   Application.Run;  end; ---------------------------------------------------------------------- rvk · 2019-07-11 07:12 Yes, it's the same with removing the empty if statement in my last clean example. The code shouldn't do anything but removing or changing it makes the crash go away. ---------------------------------------------------------------------- wp · 2019-07-11 07:46 Then somebody (rvk?) should use rvk's demo in a bug report, better than nothing and perfectly reproducible. But we should be sure that the bug has not yet been fixed in the meantime. When I compile and run rvk's demo with FPC trunk the crash does not appear any more. Regarding the complexity of the issue, this does not mean much, I know, but nanobit, can you confirm the same with your own test program(s)? ---------------------------------------------------------------------- rvk · 2019-07-11 08:12 Quote from: wp on July 09, 2019, 10:23:49 pm- Laz trunk / fpc 3.0.4 (32 bit) --> ERROR - Laz trunk / fpc trunk (32 bit)  ---> NO ERROR With the original in combination with trunk you also didn't get the error. Later this morning, I will also refresh my trunk installation and try it with fpc trunk 32bit. ---------------------------------------------------------------------- Bart · 2019-07-11 08:57 If you cannot get it to crash in a plain fpc program, it's very unlikely that some fpc devel will investigate this. I wrote a simple string manipulating program that does 400000 string operations including calls to procedures with a string as parameter (var, value, const, constref) and 80000 calls to str(). It refuses to crash. Heaptrace also does not barf on it. This is with fpc 3.0.4 and fpc trunk. Bart ---------------------------------------------------------------------- Bart · 2019-07-11 09:14 I cannot get rvk's clean example (#72) to crash. Lazarus 2.1.0 r61175 FPC 3.0.4 i386-win32-win32/win64, tested 64 and 32 bit Lazarus 2.1.0 r61564 FPC 3.3.1 i386-win32-win32/win64, tested 64 and 32 bit (fpc trunk r42348) Bart ---------------------------------------------------------------------- wp · 2019-07-11 09:31 For me, both examples of replay #71 as well as the clean example of reply #72 crash with Lazarus 2.1.0 r61542M FPC 3.0.4 i386-win32-win32/win64. They do not crash with Lazarus 2.1.0 r61564M FPC 3.3.1 i386-win32-win32/win64 r42348 [EDIT] Seeing the different Laz trunk svn versions I updated my standard trunk installation (-->Lazarus 2.1.0 r61564M FPC 3.0.4 i386-win32-win32/win64). Now the example #2 no longer produces the error, but example #1 still does as well as the "clean" example. Considering the dependence of this bug on numerous unknown parameters I fear it will not be possible to verify that a fix is successful... ---------------------------------------------------------------------- rvk · 2019-07-11 10:10 Might be related. Not sure. From the logs. Fixed in 3.1.1. Revision: 34687 Author: michael Date: zondag 9 oktober 2016 10:16:15 Message: * Fix bug 30701: allow formatting arguments in str() and writeln() ---- Modified : /trunk/packages/fcl-passrc/src/pastree.pp Modified : /trunk/packages/fcl-passrc/src/pparser.pp Modified : /trunk/packages/fcl-passrc/tests/tcstatements.pas Modified : /trunk/packages/fcl-passrc/tests/tctypeparser.pas ---------------------------------------------------------------------- Cyrax · 2019-07-11 10:26 Quote from: rvk on July 11, 2019, 12:10:51 pmMight be related. Not sure. From the logs. Fixed in 3.1.1. Revision: 34687 Author: michael Date: zondag 9 oktober 2016 10:16:15 Message: * Fix bug 30701: allow formatting arguments in str() and writeln() ---- Modified : /trunk/packages/fcl-passrc/src/pastree.pp Modified : /trunk/packages/fcl-passrc/src/pparser.pp Modified : /trunk/packages/fcl-passrc/tests/tcstatements.pas Modified : /trunk/packages/fcl-passrc/tests/tctypeparser.pas No, that fix is only for pascal parser and pas2js which uses it to transpile pascal to javascript. Compiler uses own parser. ---------------------------------------------------------------------- rick2691 · 2019-07-11 10:28 Just an observation... It seems evident to me that a dynamic string isn't protected by a fixed allocation, and that its thread can be randomly overwritten. That process can also clear out its garbage by a subsequent write that is luckily the same or greater size and has compatible data. That is why a global string of unfixed or random length becomes problematic. Likewise, a global integer, real, double, or an array do not pose problems ... they have fixed allocations. So using "string[255]" is actually an array of sorts, and is assigned a safe domain. ---------------------------------------------------------------------- rvk · 2019-07-11 10:33 Quote from: rick2691 on July 11, 2019, 12:28:13 pmSo using "string[255]" is actually an array of sorts, and is assigned a safe domain. Yes, I found that using array[0..1000] of char instead of string also fixed the problem. Using old string[255] should also work because that's a array[0..255] of char. So, my initial thought was also that the characters where written outside of the reserved area of the string. (You can also use ShortString.  ShortString = String[255]; ) Also... ShortString (and String[255]) shouldn't be reference counted. But I can't imagine Str() doesn't handle the reference counter correctly. Setting {$H-} instead of {$H+} at the top would fix it too because all strings would become shortstrings. ---------------------------------------------------------------------- metis · 2019-07-11 12:02 @rick2691 I tried Your 'Laz-CmdRPN - Copy.zip' (with HeapTrc disabled) and entered, e.g.: (Sorry Guys: This ZIP was already posted at Page #3: https://forum.laz arus.freepascal.org/index.php/topic,45872.msg325980.html#msg325980, but  I got no Internet at Home and You marched on a lot since I accessed Internet the last Time.)   <22> -> -> <55> -> <+> -> Close: no Error   <22> -> -> <55> -> Close: no Error   <2> -> -> <5> -> <+> -> Close: no Error   <2> -> -> <5> -> Close: ERROR (see attached 'ErrorOnClose.jpg') No matter, if the above Sequence was typed or clicked. Then I tried <123> -> -> <456> -> <+> -> Close: if clicked, there is no Error, but if typed the same ERROR as above is raised. All of this no matter, if the App was closed with the Titlebar's [X] or via . That's, what You described here: https://forum.lazarus.freepascal.org/ index.php/topic,45872.msg326236.html#msg326236 (You wrote "$0040F338", but maybe it's a TypeError.) Now, here comes the News: I tried it out with my WinXP 32bit SP3 + Microsoft .NET Framework 4 (Lazarus v1.8.4 + FPC v3.0.4). -> Proven, that these Errors are not due to resp. restricted to Win10. ---------------------------------------------------------------------- BrunoK · 2019-07-11 13:20 Win 10 32 bit with CmdRPN2.zip test. Entry : <1> Results in QuoteProject CmdRPN raised exception class 'External: SIGSEGV'.  In file '..\inc\heap.inc' at line 518: remove_from_list_fixed(pmc, fixedlist); Call stack : #0 REMOVE_FREED_FIXED_CHUNKS(0x28a90f0) at ..\inc\heap.inc:518 #1 FREE_OSCHUNK(0x2898b82, 0x28a90f0) at ..\inc\heap.inc:527 #2 APPEND_TO_OSLIST(0x28a90f0) at ..\inc\heap.inc:556 #3 SYSFREEMEM_FIXED(0x2898b82, 0x28a95cc) at ..\inc\heap.inc:1116 #4 SYSFREEMEM(0x28a95d0) at ..\inc\heap.inc:1177 #5 fpc_freemem(0x28a95d0) at ..\inc\heap.inc:368 #6 fpc_ansistr_decr_ref(0x19fc021) at ..\i386\i386.inc:1455 #7 WIDEINITS_$WIN32WSEXTDLGS at :0 #8 fpc_finalize(0x558658, 0x5723c0) at ..\inc\rtti.inc:182 #9 ARRAYRTTI(0x558640, 0x57d064, {procedure (POINTER, POINTER)} 0x266fdc0) at ..\inc\rtti.inc:144 #10 fpc_finalize(0x558640, 0x57d054) at ..\inc\rtti.inc:193 #11 RECORDRTTI(0x5585a0, 0x57d0e1, {procedure (POINTER, POINTER)} 0x266fdf4) at ..\inc\rtti.inc:112 #12 fpc_finalize(0x5585a0, 0x57d078) at ..\inc\rtti.inc:198 #13 SYSUTILS_$$_finalize$ at :0 #14 FINALIZEUNITS at ..\inc\system.inc:922 #15 INTERNALEXIT at ..\inc\system.inc:998 #16 DO_EXIT at ..\inc\system.inc:1041 #17 main at CmdRPN.lpr:59 It does not happen using heaptrc, cmem and cmem with heaptrc (experimental) but those allocate memory in different chunk sizes. Punctually adding for example :Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TAppForm.RegBox1Change(Sender: TObject);var  lTmpStr : string;begin  lTmpStr := TmpStr;etc.. also  seems to hide (?) the bug. All I can think about it is that lTmpStr := TmpStr does modify the reference count of TmpStr. What seems to be causing trouble is the use of ansistring. From what I could trace, the strings have sufficient memory for the Str(Reg1: 0: Dsp, TmpStr); procedure which uses internally a shortstring. At every stage in the trace the ansisstring buffers seem to getmem sufficient memory to hold the intermediate ansistrings. So a spurious update of an ansistring (maybe in a freed bloc because the part of Str() function that deals with copying the shortstring buffer to the result does many memory operations) must write something in the heap memory to damage the heap management, maybe such as writing to a previously FreeMem'd location and crashing the chain of available chunks. Problem seems to be the reference counting of ansistring and all the freemem / getmem involved. What would be interesting is if someone manages to setup a program that shows the discussed problem before exiting the program. ---------------------------------------------------------------------- Bart · 2019-07-11 14:09 Quote from: rick2691 on July 11, 2019, 12:28:13 pm and that its thread can be randomly overwritten. That process can also clear out its garbage by a subsequent write that is luckily the same or greater size and has compatible data. What have threads got to do with this topic? All writing to the string in this example happens in the same thread anyway. Bart ---------------------------------------------------------------------- Bart · 2019-07-11 14:54 Yes I can get cmdrpn2.zip to crash with fpc 3.0.4: 1 It won't crash with fpc trunk though. Probably not related, but the "if TmpStr <> RegBox1.Text" in OnChange somehow triggers another OnChange, why's that? The above sequence triggers 3 onchanges. If I comment out the "if TmpStr <> RegBox1.Text" I only get 2 OnChanges Bart ---------------------------------------------------------------------- rvk · 2019-07-11 15:05 Quote from: Bart on July 11, 2019, 04:54:57 pmProbably not related, but the "if TmpStr <> RegBox1.Text" in OnChange somehow triggers another OnChange, why's that? The above sequence triggers 3 onchanges. If I comment out the "if TmpStr <> RegBox1.Text" I only get 2 OnChanges That's also what I saw with "if Edit1.Text <> 'a' then ". It triggered the crash ending the program. When commenting out that line (which factually does NOTHING) the crash went away. I don't think the "if TmpStr <> RegBox1.Text" triggers an OnChange but there is some code overwritten with garbage (by Str()) which causes some code to crash (or jump to inexplicable places). ---------------------------------------------------------------------- Bart · 2019-07-11 16:51 If you comment out the call to Str() in TAppForm.RegBox1Change then you only get 2 OnChanges with the sequence <1> Changing TmpStr inside TAppForm.RegBox1Change in any way (not using Str()) and then querying the content of RegBox1.Text will trigger a 3rd OnChange to occur. This happens also if Icomment out all the calls to Str() inside the program. Bart ---------------------------------------------------------------------- rvk · 2019-07-11 20:58 Can you check out if Sender is the same all 3 times? Or if the OnChange is really triggered by the Change() procedure (by overriding it and seeing if that is also called three times). It's strange that even without Str() this happens. That could indeed mean it's some kind of reference count problem. ---------------------------------------------------------------------- Bart · 2019-07-11 22:11 Sender is always RegBox1. If you make TmpStr a private var of TAppForm, then only 2 OnChanges occur. Bart ---------------------------------------------------------------------- BrunoK · 2019-07-12 08:35 Looking at the generated code in assembler, my conclusion is that the compiler adds a before and that does a FreeMem  with not very clear consequences. Proposed code to circumvent the problem : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  procedure TAppForm.RegBox1Change(Sender: TObject);var  lShortStr : shortstring;begin  Str(Reg1: 0: Dsp, lShortStr); // First to a shortstring  TmpStr := lShortStr;          // then assign it to the ansistring  if TmpStr <> RegBox1.Text then  begin    // the above if line causes error when exiting program  end;end; procedure TAppForm.UpdDsp;var  lShortStr : shortstring;begin  Str(Reg1: 0: Dsp, lShortStr); // First to a shortstring  TmpStr := lShortStr;          // then assign it to the ansistring  RegBox1.Text := TmpStr;end; ---------------------------------------------------------------------- rvk · 2019-07-12 09:07 Just changing {$I+} to {$I-} fixes it too, with much more certainty to no more side-effects about ref-counting. We can conclude there is something fishy about the combination of str() with decimals in FPC 3.0.4 Since it can't be reproduced in later version, there is a high probability it is fixed in those versions. Using ShortString, {$H-} or intermediate variables can fix it temporarily in older versions. The firing twice of the OnChange event lies in the TControl.RealSetText(const Value: TCaption); Before reaching it, the Text should already have been changed by TWin32WSCustomEdit.SetText() but somehow the RealGetText = Value doesn't exit that procedure (hence the second firing of OnChange due to the CM_TEXTCHANGED). Maybe this is also due to the fact TmpStr was already freed and the wrong value was passed to the TEdit at some point. But that also doesn't seem to happen in later versions anymore. ---------------------------------------------------------------------- rick2691 · 2019-07-12 11:26 @Bart I new I was using the wrong word when I typed "thread," but I was meaning its "sequence of characters or data." Sorry for being ambiguous. @rvk Have you looked at the code... TmpStr:= FloatToStrF(Reg1,ffExponent,17,0); Can FloatToStrF have the same issue as Str() has? ---------------------------------------------------------------------- rick2691 · 2019-07-12 12:23 Additionally... UpdDsp, UpdKey, UpdSto, Hms2Hrs, and Hrs2Hms use a decimal formatting Str() FormCloseQuery uses Str() without decimal formatting. ---------------------------------------------------------------------- wp · 2019-07-12 13:39 Quote from: rick2691 on July 12, 2019, 01:26:11 pmCan FloatToStrF have the same issue as Str() has? I think so, it uses Str() with decimals internally. I have not seen them in the Format() function which does use str() but without the decimals parameter. ---------------------------------------------------------------------- rvk · 2019-07-12 13:43 Because your program isn't really string-oriented (long strings etc.) I wouldn't take any chances and just change the {$I+} to {$I-} and be done with it. It's the safest way. Otherwise move the TmpStr to local variables there where you need it. Using it as global variable (or even as class-property) will give the same problem (which is probably a reference-count problem surrounding str() and/or global string variables in fpc 3.0.4 and lower). ---------------------------------------------------------------------- rick2691 · 2019-07-12 14:26 I have already made TmpStr a local variable, and implemented the Str() to lshortstring as someone has suggested. It has been operating without fail ever since. But in UpdDsp and UpdSto there are multiple writes to TmpStr. I don't see how it can be protected within the function block. It should be just as vulnerable with that situation. ---------------------------------------------------------------------- rvk · 2019-07-12 14:53 Quote from: rick2691 on July 12, 2019, 04:26:12 pmI have already made TmpStr a local variable, and implemented the Str() to lshortstring as someone has suggested. It has been operating without fail ever since. Like I said, if you used {$H-} you wouldn't need to use ShortString because all Strings are automatically ShortStrings (i.e. String[255]). So that is the safest way. You wouldn't need to adjust anything else and your program will be safe for the future too. Quote from: rick2691 on July 12, 2019, 04:26:12 pmBut in UpdDsp and UpdSto there are multiple writes to TmpStr. I don't see how it can be protected within the function block. It should be just as vulnerable with that situation. Moving TmpStr to local (as LongString), you eliminate a lot of reference counting and using it (directly) in Str() wouldn't impact it as much. But with a lot of Str() with LongString, it could still go wrong (probably). But the chances of it happening are a lot less. So my suggestion would be to not use TmpStr (as LongString) directly with Str(). So you could do Str(ShortString:x:y) and assign it later to a LongString (i.e. TmpStr := Result_ShortString_From_Str) or Just add {$H-} at the top (instead of {$H+} and be done with all the hassle of checking for Long- and ShortStrings altogether. ---------------------------------------------------------------------- wp · 2019-07-12 15:21 Quote from: rvk on July 12, 2019, 04:53:16 pmJust add {$H-} at the top (instead of {$H+} and be done with all the hassle of checking for Long- and ShortStrings altogether. This recommendation is probably ok for a calculator application, but not in general, IMHO. The user at least must be aware of the consequence that strings cannot be longer than 255 characters then. ---------------------------------------------------------------------- rvk · 2019-07-12 15:43 Quote from: wp on July 12, 2019, 05:21:00 pmQuote from: rvk on July 12, 2019, 04:53:16 pmJust add {$H-} at the top (instead of {$H+} and be done with all the hassle of checking for Long- and ShortStrings altogether. This recommendation is probably ok for a calculator application, but not in general, IMHO. The user at least must be aware of the consequence that strings cannot be longer than 255 characters then. Yes, that's wat I also already mentioned in a previous post. Because the application isn't really string oriented (as calculator) the {$H-} would be the safest and fastest option. For all others you need to make certain choices. So when dealing with FPC 3.0.4 and lower in combination with Str() in {$H+} you need to be careful. In other applications I wouldn't even begin to consider using Str(n:x:y) anyway. I would use format(). I know for sure Delphi doesn't use Str() internally for format (but I'm not sure if FPC does). ---------------------------------------------------------------------- rick2691 · 2019-07-12 16:19 @rvk et.al. Thanks for your diligence. Its been a mess.