Lazarus

Programming => Operating Systems => Windows => Topic started by: rick2691 on June 24, 2019, 06:17:51 pm

Title: Windows 10 and FormClose
Post by: rick2691 on June 24, 2019, 06:17:51 pm
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]
  1. procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
  2. begin
  3. CloseAction:= caFree;
  4. (* // alternately for mechanical choice...
  5. if MessageDlg('Close application?', mtConfirmation, [mbYes, mbNo], 0) = mrYes
  6.    then CloseAction:= caFree
  7.    else CloseAction:= caMinimize;
  8. *)
  9. end;
  10.  
  11. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: boolean);
  12. var CfgFile: TextFile;
  13.     DatStr: string;
  14.     OK: boolean;  // DatOK: boolean;
  15.     IOval: integer;  // longint;
  16. begin
  17. AssignFile(CfgFile, PrgmFolder+'CmdRPN.cfg');
  18. {$I-} Rewrite(CfgFile) {$I+};
  19. IOval:=IOresult; OK:=(IOval=0);
  20. if OK then   // was DatOK
  21.    begin try
  22.          Str(Reg0,DatStr); Writeln(CfgFile,DatStr);  // register display
  23.          Str(Reg1,DatStr); Writeln(CfgFile,DatStr);
  24.          Str(Reg2,DatStr); Writeln(CfgFile,DatStr);
  25.          Str(Reg3,DatStr); Writeln(CfgFile,DatStr);
  26.          Str(Reg4,DatStr); Writeln(CfgFile,DatStr);
  27.  
  28.          Str(Mem1,DatStr); Writeln(CfgFile,DatStr);  // storage memory
  29.          Str(Mem2,DatStr); Writeln(CfgFile,DatStr);
  30.          Str(Mem3,DatStr); Writeln(CfgFile,DatStr);
  31.          Str(Mem4,DatStr); Writeln(CfgFile,DatStr);
  32.          Str(Mem5,DatStr); Writeln(CfgFile,DatStr);
  33.          Str(Mem6,DatStr); Writeln(CfgFile,DatStr);
  34.          Str(Mem7,DatStr); Writeln(CfgFile,DatStr);
  35.          Str(Mem8,DatStr); Writeln(CfgFile,DatStr);
  36.          Str(Mem9,DatStr); Writeln(CfgFile,DatStr);
  37.  
  38.          Str(Dsp,DatStr); Writeln(CfgFile,DatStr); // decimal display
  39.          if HrsMode=true then DatStr:='1'  // HmsMode ...Dms
  40.                          else DatStr:='0'; // HrsMode ...Dec
  41.          Writeln(CfgFile,DatStr); // angle mode
  42.  
  43.          finally
  44.          Flush(CfgFile);
  45.          CloseFile(CfgFile);
  46.          CanClose:= true;
  47.          end;  // end try
  48.    end
  49.    else  begin
  50.          CloseFile(CfgFile);
  51.          CanClose:= false;
  52.          end;
  53. end;
  54.  
Title: Re: Windows 10 and FormClose
Post by: ASerge on June 24, 2019, 07:44:19 pm
With debugging information, you can get a stack trace to find the code that generates the error.
Title: Re: Windows 10 and FormClose
Post by: rick2691 on June 25, 2019, 02:05:01 pm
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]
  1. procedure RaiseGDBException(const Msg: string);  // *lclproc.pas*
  2. begin
  3.   debugln(rsERRORInLCL, Msg);
  4.   // creates an exception, that gdb catches:
  5.   debugln(rsCreatingGdbCatchableError);
  6.   DumpStack;
  7.   if (length(Msg) div (length(Msg) div 10000))=0 then ;   // *line 902*
  8. end;
  9.  

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.
Title: Re: Windows 10 and FormClose
Post by: rick2691 on June 25, 2019, 02:30:20 pm
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.
Title: Re: Windows 10 and FormClose
Post by: marcov on June 25, 2019, 02:46:50 pm
Code: Pascal  [Select]
  1. if (length(Msg) div (length(Msg) div 10000))=0 then ;   // *line 902*
  2. 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.
Title: Re: Windows 10 and FormClose
Post by: rick2691 on June 25, 2019, 03:03:01 pm
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.
Title: Re: Windows 10 and FormClose
Post by: rvk on June 25, 2019, 03:15:18 pm
Code: Pascal  [Select]
  1. if (length(Msg) div (length(Msg) div 10000))=0 then ;   // *line 902*
  2. 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]
  1. procedure RaiseGDBException(const Msg: string);
  2. begin
  3.   DebugLn(lrsERRORInCode, Msg);
  4.   // creates an exception, that gdb catches:
  5.   DebugLn(lrsCreatingGdbCatchableError);
  6.   DumpStack;
  7.   {$ifndef HASAMIGA} // On Amiga Division by 0 is not catchable, just crash
  8.   if (length(Msg) div (length(Msg) div 10000))=0 then ;
  9.   {$endif}
  10. 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.
Title: Re: Windows 10 and FormClose
Post by: nanobit on June 26, 2019, 11:47:02 am
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

Title: Re: Windows 10 and FormClose
Post by: Thaddy on June 26, 2019, 12:27:32 pm
Rick, 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  8) :P :P
Title: Re: Windows 10 and FormClose
Post by: nanobit on June 26, 2019, 12:35:39 pm
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.... :)
Title: Re: Windows 10 and FormClose
Post by: rvk on June 26, 2019, 12:36:29 pm
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.
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.
Quote
Windows 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).
Title: Re: Windows 10 and FormClose
Post by: rvk on June 26, 2019, 12:40:13 pm
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.
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.
Title: Re: Windows 10 and FormClose
Post by: Thaddy on June 26, 2019, 12:41:39 pm
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!)
Title: Re: Windows 10 and FormClose
Post by: rvk on June 26, 2019, 12:44:25 pm
<slightly off topic>
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.
</slightly off topic>
Title: Re: Windows 10 and FormClose
Post by: Thaddy on June 26, 2019, 12:44:51 pm
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.
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.... :o :( :(
Title: Re: Windows 10 and FormClose
Post by: Thaddy on June 26, 2019, 12:53:21 pm
<slightly off topic>
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.
</slightly off topic>
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)
Title: Re: Windows 10 and FormClose
Post by: Thaddy on June 26, 2019, 01:04:07 pm
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)  8) :D )
I am CEH as you know.
Title: Re: Windows 10 and FormClose
Post by: rvk on June 26, 2019, 01:05:55 pm
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).

Quote
WHY 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.
Title: Re: Windows 10 and FormClose
Post by: rick2691 on June 26, 2019, 02:49:59 pm
@rvk

Quote
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.

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.
Title: Re: Windows 10 and FormClose
Post by: Thaddy on June 26, 2019, 04:00:50 pm
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...
Title: Re: Windows 10 and FormClose
Post by: Thaddy on June 26, 2019, 04:08:16 pm
Luckily 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... >:D 8-)
Title: Re: Windows 10 and FormClose
Post by: ASerge on June 26, 2019, 09:13:04 pm
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]
  1. procedure RaiseGDBException(const Msg: string);  // *lclproc.pas*
  2. begin
  3.   debugln(rsERRORInLCL, Msg);
  4.   // creates an exception, that gdb catches:
  5.   debugln(rsCreatingGdbCatchableError);
  6.   DumpStack;
  7.   if (length(Msg) div (length(Msg) div 10000))=0 then ;   // *line 902*
  8. end;
  9.  
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.
Title: Re: Windows 10 and FormClose
Post by: metis on June 28, 2019, 12:57:43 pm
@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
Quote
In some cases external libraries (...) can toggle  the default state to ignore

Quote
I was hoping that someone else would have had a similar issue and a quicker fix
I 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 ?
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 01, 2019, 08:07:20 pm
@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.
Title: Re: Windows 10 and FormClose
Post by: mas steindorff on July 01, 2019, 09:43:25 pm
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.
Title: Re: Windows 10 and FormClose
Post by: ASerge on July 01, 2019, 09:50:26 pm
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.
You can make an example? On my machine the following code is executed without problems with x32 and x64:
Code: Pascal  [Select]
  1. {$APPTYPE CONSOLE}
  2. {$IFDEF FPC} {$MODE OBJFPC} {$ENDIF}
  3. {$LONGSTRINGS ON}
  4.  
  5. uses Math;
  6.  
  7. var
  8.   X: ValReal = 1123;
  9.   S: string;
  10. begin
  11.   X := X * Power(10, -240);
  12.   Str(X:0:4, S);
  13.   Writeln(S);
  14.   Writeln(X);
  15.   Readln;
  16. end.
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 02, 2019, 12:07:09 pm
@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]
  1. //These are the global variables
  2.  
  3. var
  4.   AppForm: TAppForm;
  5.   Reg0,Reg1,Reg2,Reg3,Reg4,Lst,Hrs,Hms: double; // reg0 is for swapping display stack
  6.   Mem1,Mem2,Mem3,Mem4,Mem5,Mem6,Mem7,Mem8,Mem9: double;
  7.   Err,Dsp: integer;
  8.   TmpStr,LstDsp,PrgmFolder: string;
  9.   NewReg,SavReg,StoActive,HrsMode: boolean;
  10.  
  11.  
  12. //This is the function that creates an onclose crash.
  13. //If I exclude this call the program does not crash at OnClose.
  14. //Debug indicates that it is Str(Reg1:0:Dsp,TmpStr) ... it is as if Reg1 has junk data in it.
  15. //But I don't understand why UpdDsp is firing at OnClose to begin with.
  16.  
  17. procedure TAppForm.UpdDsp;
  18. var x,z:integer;
  19. begin
  20. try
  21. Str(Reg1:0:Dsp,TmpStr); // *** crash point at OnClose ***
  22. x:= pos('.',TmpStr);
  23. z:= length(TmpStr);
  24. if (x>17)or(z>17) then  // this only fires when a number is very large ... large numbers are not the problem.
  25.    begin
  26.    TmpStr:= FloatToStrF(Reg1,ffExponent,17,0); //showmessage(TmpStr);
  27.    end;
  28. RegBox1.text:= TmpStr;
  29. finally
  30. end;
  31.  
  32. try
  33. Str(Reg2:0:Dsp,TmpStr);
  34. x:= pos('.',TmpStr);
  35. z:= length(TmpStr);
  36. if (x>17)or(z>17) then
  37.    begin
  38.    TmpStr:= FloatToStrF(Reg2,ffExponent,17,0); //showmessage(TmpStr);
  39.    end;
  40. RegBox2.text:= TmpStr;
  41. finally
  42. end;
  43.  
  44. try
  45. Str(Reg3:0:Dsp,TmpStr);
  46. x:= pos('.',TmpStr);
  47. z:= length(TmpStr);
  48. if (x>17)or(z>17) then
  49.    begin
  50.    TmpStr:= FloatToStrF(Reg3,ffExponent,17,0); //showmessage(TmpStr);
  51.    end;
  52. RegBox3.text:= TmpStr;
  53. finally
  54. end;
  55.  
  56. try
  57. Str(Reg4:0:Dsp,TmpStr);
  58. x:= pos('.',TmpStr);
  59. z:= length(TmpStr);
  60. if (x>17)or(z>17) then
  61.    begin
  62.    TmpStr:= FloatToStrF(Reg4,ffExponent,17,0); //showmessage(TmpStr);
  63.    end;
  64. RegBox4.text:= TmpStr;
  65. finally
  66. end;
  67. ResetFocus;
  68. Update;
  69. end;
  70.  
  71.  
  72. //I use this exception handler which writes to a log file.
  73. //It does not activate at OnClose, so the crash is not the program.
  74. //Yet debug is indicating that the crash is on account of Str(Reg1:0:Dsp,TmpStr).
  75. //It is as if there are some trashed functions or variables that are not being purged at OnClose.
  76.  
  77. procedure TAppForm.LogException(Sender: TObject; E: Exception);
  78. var ErrorFile: TextFile;
  79.     ErrorInfo: String;
  80.     AppPath,SenderMsg: string;
  81. begin
  82. SenderMsg:= E.Message;  // e.message contains line-feed
  83. AppPath:= ExtractFilePath(ParamStr(0));
  84. AssignFile(ErrorFile, AppPath+'CmdRPN.log');
  85. if FileExists(AppPath+'CmdRPN.log')
  86.    then Append(ErrorFile)
  87.    else Rewrite(ErrorFile);
  88. ErrorInfo:= DateTimeToStr(Now)+' Unhandled exception';
  89. if Assigned(Sender)
  90.    then ErrorInfo:= ErrorInfo+' in '+Sender.UnitName+'->'+Sender.ClassName;
  91. ErrorInfo:= ErrorInfo+': '+SenderMsg;
  92. try WriteLn(ErrorFile, ErrorInfo);
  93.     finally
  94.     CloseFile(ErrorFile);
  95.     ShowMessage('Application fault... message saved: CmdRPN.log');
  96.     end;
  97. end;
  98.  
  99. //These are the Close functions that I employ ... there is no call to UpdDsp in them.
  100.  
  101. procedure TAppForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
  102. begin
  103. CloseAction:= caFree;
  104. end;
  105.  
  106. procedure TAppForm.FormCloseQuery(Sender: TObject; var CanClose: boolean);
  107. var CfgFile: TextFile;
  108.     DatStr: string;
  109.     OK: boolean;  // DatOK: boolean;
  110.     IOval: integer;  // longint;
  111. begin
  112. AssignFile(CfgFile, PrgmFolder+'CmdRPN.cfg');
  113. {$I-} Rewrite(CfgFile) {$I+};
  114. IOval:=IOresult; OK:=(IOval=0);
  115. if OK then   // was DatOK
  116.    begin try
  117.          Str(Reg0,DatStr); Writeln(CfgFile,DatStr);  // register display
  118.          Str(Reg1,DatStr); Writeln(CfgFile,DatStr);
  119.          Str(Reg2,DatStr); Writeln(CfgFile,DatStr);
  120.          Str(Reg3,DatStr); Writeln(CfgFile,DatStr);
  121.          Str(Reg4,DatStr); Writeln(CfgFile,DatStr);
  122.          Str(Mem1,DatStr); Writeln(CfgFile,DatStr);  // storage memory
  123.          Str(Mem2,DatStr); Writeln(CfgFile,DatStr);
  124.          Str(Mem3,DatStr); Writeln(CfgFile,DatStr);
  125.          Str(Mem4,DatStr); Writeln(CfgFile,DatStr);
  126.          Str(Mem5,DatStr); Writeln(CfgFile,DatStr);
  127.          Str(Mem6,DatStr); Writeln(CfgFile,DatStr);
  128.          Str(Mem7,DatStr); Writeln(CfgFile,DatStr);
  129.          Str(Mem8,DatStr); Writeln(CfgFile,DatStr);
  130.          Str(Mem9,DatStr); Writeln(CfgFile,DatStr);
  131.          Str(Dsp,DatStr); Writeln(CfgFile,DatStr); // decimal display
  132.          if HrsMode=true then DatStr:='1'  // HmsMode ...Dms
  133.                          else DatStr:='0'; // HrsMode ...Dec
  134.          Writeln(CfgFile,DatStr); // angle mode
  135.          finally
  136.          Flush(CfgFile);
  137.          CloseFile(CfgFile);
  138.          CanClose:= true; //showmessage('closing by CanClose');  // good
  139.          end;  // end try
  140.    end else begin
  141.             CloseFile(CfgFile);
  142.             CanClose:= false;
  143.             end;
  144. CanClose:= true; //showmessage('closing by CloseQuery');  // good
  145. end;
Title: Re: Windows 10 and FormClose
Post by: wp on July 02, 2019, 12:29:04 pm
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.
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 02, 2019, 01:53:39 pm
@wp
Quote
Why 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.
Quote
Code 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.
Title: Re: Windows 10 and FormClose
Post by: wp on July 02, 2019, 02:53:04 pm
Quote
Code 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.
Title: Re: Windows 10 and FormClose
Post by: howardpc on July 02, 2019, 04:16:37 pm
@wp
Quote
Why 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.
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 02, 2019, 08:57:06 pm
@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.
Title: Re: Windows 10 and FormClose
Post by: ASerge on July 03, 2019, 07:22:44 pm
Quote
Code 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.
Title: Re: Windows 10 and FormClose
Post by: metis on July 04, 2019, 01:01:06 pm
@rick2691

Quote
I tried the SetExceptionMask...It did not help
You must put it at the very Beginning of the Program - Did You do so ?

Quote
The program is a calculator + I do not believe that these things are due to my coding
I 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.

Quote
It only crashes when closing the application
Did You try out the HeapTrc-Unit (-gh Switch) to check Memory-Allocation/Deallocation ?
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 04, 2019, 05:25:32 pm
It is really difficult to send an attachment. It has posted as an another thread with the same title.
Title: Re: Windows 10 and FormClose
Post by: metis on July 04, 2019, 06:42:19 pm
@rick2691

Quote
It has posted as an another thread with the same title
Hope, 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.

***************************************************************************************
Title: Re: Windows 10 and FormClose
Post by: wp on July 04, 2019, 07:02:10 pm
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
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 04, 2019, 08:45:37 pm
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.
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 04, 2019, 11:43:12 pm
@wp

You also need to launch from an exe. If you do it by run, it is protected.
Title: Re: Windows 10 and FormClose
Post by: wp on July 05, 2019, 01:46:35 pm
Still cannot reproduce...

When scanning your code I saw these things which are unusual. I think, however, that they do not cause your issues:
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 06, 2019, 07:10:40 pm
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?
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 06, 2019, 07:26:21 pm
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
Title: Re: Windows 10 and FormClose
Post by: ASerge on July 07, 2019, 12:41:42 am
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.
Title: Re: Windows 10 and FormClose
Post by: Cyrax on July 07, 2019, 01:27:35 am
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.
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 07, 2019, 06:11:37 pm
@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?
Title: Re: Windows 10 and FormClose
Post by: 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?
Title: Re: Windows 10 and FormClose
Post by: Cyrax on July 08, 2019, 08:42:35 am
@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
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 08, 2019, 02:55:57 pm
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.
Title: Re: Windows 10 and FormClose
Post by: rvk on July 09, 2019, 09:34:25 am
You 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?
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 09, 2019, 12:54:46 pm
@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.
Title: Re: Windows 10 and FormClose
Post by: rvk on July 09, 2019, 01:07:08 pm
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?
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 09, 2019, 01:53:24 pm
@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]
  1. procedure TAppForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
  2. //begin
  3. //CloseAction:= caFree;
  4.  
  5. var
  6.   i: Integer;
  7.   C: TComponent;
  8. begin
  9.   for i := ComponentCount - 1 downto 0 do
  10.   begin
  11.     C := Components[i];
  12.     if C is TCustomForm then
  13.     begin
  14.       //writeln('Component[',i,'] is  Form: ',C.ClassName,':',C.Name);
  15.       FreeAndNil(C);
  16.     end;
  17.   end;
  18. 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.

Title: Re: Windows 10 and FormClose
Post by: rvk on July 09, 2019, 02:01:13 pm
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.

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.
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).

Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 09, 2019, 04:55:24 pm
@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.
Title: Re: Windows 10 and FormClose
Post by: rvk on July 09, 2019, 05:04:02 pm
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.
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).

Quote
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.
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.
Title: Re: Windows 10 and FormClose
Post by: ASerge on July 09, 2019, 06:05:14 pm
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.
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.
Title: Re: Windows 10 and FormClose
Post by: rvk on July 09, 2019, 09:23:09 pm
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.
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)
Title: Re: Windows 10 and FormClose
Post by: wp on July 09, 2019, 09:58:49 pm
For now I have discovered something promising.

Code: Pascal  [Select]
  1. procedure TAppForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
  2. //begin
  3. //CloseAction:= caFree;
  4.  
  5. var
  6.   i: Integer;
  7.   C: TComponent;
  8. begin
  9.   for i := ComponentCount - 1 downto 0 do
  10.   begin
  11.     C := Components[i];
  12.     if C is TCustomForm then
  13.     begin
  14.       //writeln('Component[',i,'] is  Form: ',C.ClassName,':',C.Name);
  15.       FreeAndNil(C);
  16.     end;
  17.   end;
  18. 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.
Title: Re: Windows 10 and FormClose
Post by: rvk on July 09, 2019, 10:02:46 pm
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.
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.
Title: Re: Windows 10 and FormClose
Post by: wp on July 09, 2019, 10:23:49 pm
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.

Title: Re: Windows 10 and FormClose
Post by: rvk on July 09, 2019, 11:01:22 pm
It 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.
Title: Re: Windows 10 and FormClose
Post by: wp on July 09, 2019, 11:12:59 pm
It 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.
Title: Re: Windows 10 and FormClose
Post by: rvk on July 09, 2019, 11:31:39 pm
It only happens for me when you have no .cfg file.

I noticed that without it, 1 <enter> 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.
Title: Re: Windows 10 and FormClose
Post by: wp on July 09, 2019, 11:40:55 pm
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).
Title: Re: Windows 10 and FormClose
Post by: rvk on July 09, 2019, 11:43:58 pm
The problem are in these lines (and the recursion of all the children).

Code: Pascal  [Select]
  1.     with Control do
  2.     begin
  3.       Left := ScaleX(Left, FromDPI);
  4.       Top := ScaleY(Top, FromDPI);
  5.       Width := ScaleX(Width, FromDPI);
  6.       Height := ScaleY(Height, FromDPI);
  7.     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.
Title: Re: Windows 10 and FormClose
Post by: wp on July 10, 2019, 12:12:05 am
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]
  1.     Left := MulDiv(Left, 96, 96);
  2.     Top := MulDiv(Top, 96, 96);
  3.     Width := MulDiv(Width, 96, 96);
  4.     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]
  1. function MathRound(AValue: ValReal): Int64; inline;
  2. begin
  3.   if AValue >= 0 then
  4.     Result := Trunc(AValue + 0.5)
  5.   else
  6.     Result := Trunc(AValue - 0.5);
  7. end;
  8.  
  9. function MulDiv(nNumber, nNumerator, nDenominator: Integer): Integer;
  10. begin
  11.   if nDenominator = 0 then
  12.     Result := -1
  13.   else
  14.   if nNumerator = nDenominator then
  15.     Result := nNumber
  16.   else
  17.     Result := MathRound(int64(nNumber) * int64(nNumerator) / nDenominator);
  18. end;

Got the feeling the bug is somewhere else...
Title: Re: Windows 10 and FormClose
Post by: rvk on July 10, 2019, 12:16:05 am
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.
Title: Re: Windows 10 and FormClose
Post by: wp on July 10, 2019, 12:21:36 am
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.
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]
  1.     SetBounds(
  2.       ScaleX(Left, FromDPI),
  3.       ScaleY(Top, FromDPI),
  4.       ScaleX(Width, FromDPI),
  5.       ScaleY(Height, FromDPI)
  6.     );

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.
Title: Re: Windows 10 and FormClose
Post by: wp on July 10, 2019, 09:37:38 am
Now I reloaded the original project, unchecked the heaptrc, commented the ScaleDPI call -> bug is back. Frustrating...
Title: Re: Windows 10 and FormClose
Post by: rvk on July 10, 2019, 10:20:08 am
Now 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.
Title: Re: Windows 10 and FormClose
Post by: rvk on July 10, 2019, 10:32:45 am
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.

Title: Re: Windows 10 and FormClose
Post by: rvk on July 10, 2019, 11:41:37 am
Just for the other eyes... a (really) stripped down version.

Just pressing 1 <enter> <alt+f4> is enough to get the error (don't mind the display output).

FYI. This is called stripping a project (compared to the original)  :D

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.
Title: Re: Windows 10 and FormClose
Post by: rvk on July 10, 2019, 12:48:14 pm
Okay, reproducible with clean empty project.

Code: Pascal  [Select]
  1. Reg1 := 0.0;
Code: Pascal  [Select]
  1.   Reg1: double;
  2.   TmpStr: string;
Code: Pascal  [Select]
  1.   Str(Reg1: 0: 2, TmpStr);
  2.   if Edit1.Text <> 'a' then
  3.   begin
  4.     // the above if line causes error when exiting program
  5.   end;
  6.  
Code: Pascal  [Select]
  1.   if (Key in ['0'..'9']) or (key = '.') then  //digit keys
  2.   begin
  3.     Edit1.Text := Key;
  4.     Key := #0;
  5.   end;
  6.   if Key = #13 then   //enter key
  7.   begin
  8.     Key := #0;
  9.     Str(Reg1: 0: 2, TmpStr);
  10.     Edit1.Text := TmpStr;
  11.   end;

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 <enter> 2 <enter> <Alt+F4> 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.
Title: Re: Windows 10 and FormClose
Post by: wp on July 10, 2019, 06:29:58 pm
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...
Title: Re: Windows 10 and FormClose
Post by: rvk on July 10, 2019, 07:09:52 pm
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.
Title: Re: Windows 10 and FormClose
Post by: nanobit on July 10, 2019, 10:13:47 pm
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.
Title: Re: Windows 10 and FormClose
Post by: wp on July 10, 2019, 11:42:08 pm
Can you post a simple non-lcl demo to demonstate the issue to the compiler people?
Title: Re: Windows 10 and FormClose
Post by: nanobit on July 11, 2019, 08:56:59 am
Can 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;
Title: Re: Windows 10 and FormClose
Post by: rvk on July 11, 2019, 09:12:07 am
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.
Title: Re: Windows 10 and FormClose
Post by: wp on July 11, 2019, 09:46:54 am
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)?
Title: Re: Windows 10 and FormClose
Post by: rvk on July 11, 2019, 10:12:14 am
- 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.
Title: Re: Windows 10 and FormClose
Post by: Bart on July 11, 2019, 10:57:33 am
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
Title: Re: Windows 10 and FormClose
Post by: Bart on July 11, 2019, 11:14:58 am
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
Title: Re: Windows 10 and FormClose
Post by: wp on July 11, 2019, 11:31:55 am
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...
Title: Re: Windows 10 and FormClose
Post by: rvk on July 11, 2019, 12:10:51 pm
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 (https://bugs.freepascal.org/view.php?id=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
Title: Re: Windows 10 and FormClose
Post by: Cyrax on July 11, 2019, 12:26:35 pm
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 (https://bugs.freepascal.org/view.php?id=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.
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 11, 2019, 12:28:13 pm
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.
Title: Re: Windows 10 and FormClose
Post by: rvk on July 11, 2019, 12:33:41 pm
So 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.
Title: Re: Windows 10 and FormClose
Post by: metis on July 11, 2019, 02:02:42 pm
@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.lazarus.freepascal.org/index.php/topic,45872.msg325980.html#msg325980 (https://forum.lazarus.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> -> <Enter> -> <55> -> <+> -> Close: no Error

  <22> -> <Enter> -> <55> -> Close: no Error

  <2> -> <Enter> -> <5> -> <+> -> Close: no Error

  <2> -> <Enter> -> <5> -> Close: ERROR (see attached 'ErrorOnClose.jpg')

No matter, if the above Sequence was typed or clicked.

Then I tried <123> -> <Enter> -> <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 <Alt+F4>.

That's, what You described here: https://forum.lazarus.freepascal.org/index.php/topic,45872.msg326236.html#msg326236 (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.
Title: Re: Windows 10 and FormClose
Post by: BrunoK on July 11, 2019, 03:20:04 pm
Win 10 32 bit with CmdRPN2.zip test.

Entry : <1> <Enter> <Alt-F4>

Results in
Quote
Project 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]
  1. procedure TAppForm.RegBox1Change(Sender: TObject);
  2. var
  3.   lTmpStr : string;
  4. begin
  5.   lTmpStr := TmpStr;
  6. etc..
  7.  
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.
Title: Re: Windows 10 and FormClose
Post by: Bart on July 11, 2019, 04:09:31 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
Title: Re: Windows 10 and FormClose
Post by: Bart on July 11, 2019, 04:54:57 pm
Yes I can get cmdrpn2.zip to crash with fpc 3.0.4: 1<enter><alt-F4>
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
Title: Re: Windows 10 and FormClose
Post by: rvk on July 11, 2019, 05:05:57 pm
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
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).
Title: Re: Windows 10 and FormClose
Post by: Bart on July 11, 2019, 06:51:39 pm
If you comment out the call to Str() in TAppForm.RegBox1Change then you only get 2 OnChanges with the sequence <1><enter><alt+F4>

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
Title: Re: Windows 10 and FormClose
Post by: rvk on July 11, 2019, 10:58:02 pm
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.
Title: Re: Windows 10 and FormClose
Post by: Bart on July 12, 2019, 12:11:53 am
Sender is always RegBox1.
If you make TmpStr a private var of TAppForm, then only 2 OnChanges occur.

Bart
Title: Re: Windows 10 and FormClose
Post by: BrunoK on July 12, 2019, 10:35:57 am
Looking at the generated code in assembler, my conclusion is that the compiler adds a <fpc_ansistr_decr_ref> before <fpc_ansistr_float> and that does a FreeMem  with not very clear consequences.

Proposed code to circumvent the problem :

Code: Pascal  [Select]
  1.  
  2. procedure TAppForm.RegBox1Change(Sender: TObject);
  3. var
  4.   lShortStr : shortstring;
  5. begin
  6.   Str(Reg1: 0: Dsp, lShortStr); // First to a shortstring
  7.   TmpStr := lShortStr;          // then assign it to the ansistring
  8.   if TmpStr <> RegBox1.Text then
  9.   begin
  10.     // the above if line causes error when exiting program
  11.   end;
  12. end;
  13.  
  14. procedure TAppForm.UpdDsp;
  15. var
  16.   lShortStr : shortstring;
  17. begin
  18.   Str(Reg1: 0: Dsp, lShortStr); // First to a shortstring
  19.   TmpStr := lShortStr;          // then assign it to the ansistring
  20.   RegBox1.Text := TmpStr;
  21. end;
  22.  

Title: Re: Windows 10 and FormClose
Post by: rvk on July 12, 2019, 11:07:00 am
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.
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 12, 2019, 01:26:11 pm
@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?
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 12, 2019, 02:23:05 pm
Additionally... UpdDsp, UpdKey, UpdSto, Hms2Hrs, and Hrs2Hms use a decimal formatting Str()

FormCloseQuery uses Str() without decimal formatting.
Title: Re: Windows 10 and FormClose
Post by: wp on July 12, 2019, 03:39:41 pm
Can 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.
Title: Re: Windows 10 and FormClose
Post by: rvk on July 12, 2019, 03:43:58 pm
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).
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 12, 2019, 04:26:12 pm
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.
Title: Re: Windows 10 and FormClose
Post by: rvk on July 12, 2019, 04:53:16 pm
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.
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.

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.
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.
Title: Re: Windows 10 and FormClose
Post by: wp on July 12, 2019, 05:21:00 pm
Just 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.
Title: Re: Windows 10 and FormClose
Post by: rvk on July 12, 2019, 05:43:13 pm
Just 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).
Title: Re: Windows 10 and FormClose
Post by: rick2691 on July 12, 2019, 06:19:05 pm
@rvk et.al.

Thanks for your diligence. Its been a mess.