Recent

Author Topic: Windows 10 and FormClose  (Read 13265 times)

rvk

  • Hero Member
  • *****
  • Posts: 4157
Re: Windows 10 and FormClose
« Reply #60 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.
« Last Edit: July 09, 2019, 11:13:37 pm by rvk »

wp

  • Hero Member
  • *****
  • Posts: 7213
Re: Windows 10 and FormClose
« Reply #61 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.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

rvk

  • Hero Member
  • *****
  • Posts: 4157
Re: Windows 10 and FormClose
« Reply #62 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.

wp

  • Hero Member
  • *****
  • Posts: 7213
Re: Windows 10 and FormClose
« Reply #63 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).
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

rvk

  • Hero Member
  • *****
  • Posts: 4157
Re: Windows 10 and FormClose
« Reply #64 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.
« Last Edit: July 09, 2019, 11:53:31 pm by rvk »

wp

  • Hero Member
  • *****
  • Posts: 7213
Re: Windows 10 and FormClose
« Reply #65 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...
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

rvk

  • Hero Member
  • *****
  • Posts: 4157
Re: Windows 10 and FormClose
« Reply #66 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.

wp

  • Hero Member
  • *****
  • Posts: 7213
Re: Windows 10 and FormClose
« Reply #67 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.
« Last Edit: July 10, 2019, 12:32:37 am by wp »
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

wp

  • Hero Member
  • *****
  • Posts: 7213
Re: Windows 10 and FormClose
« Reply #68 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...
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

rvk

  • Hero Member
  • *****
  • Posts: 4157
Re: Windows 10 and FormClose
« Reply #69 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.

rvk

  • Hero Member
  • *****
  • Posts: 4157
Re: Windows 10 and FormClose
« Reply #70 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.

« Last Edit: July 10, 2019, 10:39:37 am by rvk »

rvk

  • Hero Member
  • *****
  • Posts: 4157
Re: Windows 10 and FormClose
« Reply #71 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.
« Last Edit: July 10, 2019, 12:04:24 pm by rvk »

rvk

  • Hero Member
  • *****
  • Posts: 4157
Re: Windows 10 and FormClose
« Reply #72 on: July 10, 2019, 12:48:14 pm »
Okay, reproducible with clean empty project.

  • Project > New Project > Application
  • Double click to create Formcreate
  • Paste in
Code: Pascal  [Select][+][-]
  1. Reg1 := 0.0;
  • Paste the following under the global Form1: TForm1; variable
Code: Pascal  [Select][+][-]
  1.   Reg1: double;
  2.   TmpStr: string;
  • Drop a new TEdit on the form
  • Double click the events (in Inspector) OnChange and OnKeyPress
  • Paste in the following in OnChange
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.  
  • Paste in the following in OnKeyPress
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;
  • Run the application (F9)
  • Press 1 <enter> <Alt+F4>
  • ERROR
  • If the error doesn't show up, change the Text property of the TEdit in the object inspector
  • Run the application (F9)
  • Press 1 <enter> <Alt+F4>
  • 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 <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.
« Last Edit: July 10, 2019, 12:58:55 pm by rvk »

wp

  • Hero Member
  • *****
  • Posts: 7213
Re: Windows 10 and FormClose
« Reply #73 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...
« Last Edit: July 10, 2019, 06:33:09 pm by wp »
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

rvk

  • Hero Member
  • *****
  • Posts: 4157
Re: Windows 10 and FormClose
« Reply #74 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.

 

TinyPortal © 2005-2018