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.