Recent

Author Topic: [SOLVED] Access violation when ending program / Forms with Parent 'Application'  (Read 7585 times)

alpine

  • Hero Member
  • *****
  • Posts: 1410
Sorry alpine, I again don't really understand what you suggest to do and why this should be neccessary or recommendable.
Why: because you can't be sure what you found is what you're looking for! The AV has only manifested itself once.

Sorry alpine, I again don't really understand what you suggest to do and why this should be neccessary or recommendable.
What I'm suggesting: to hunt for a dangling Self and to prove you hypothesis. It is easier (at least - doable) than waiting for the side effect of memory corruption on some other instance to reappear as an AV.

Consider the example:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$mode objfpc}{$H+}
  3. uses
  4.   {$IFDEF UNIX}
  5.   cthreads,
  6.   {$ENDIF}
  7.   {$IFDEF HASAMIGA}
  8.   athreads,
  9.   {$ENDIF}
  10.   Interfaces, // this includes the LCL widgetset
  11.   Forms, unit1
  12.   { you can add units after this };
  13.  
  14. type
  15.   TDummy = class
  16.     procedure EventHandler(Sender: TObject);
  17.   end;
  18.  
  19. {$R *.res}
  20.  
  21. procedure TDummy.EventHandler(Sender: TObject);
  22. begin
  23.   if not Assigned(Self) then // <-- Try to validate the Self pointer
  24.     Exit;
  25.   {Self.}SomeProperty := 47; // Will corrupt something?!
  26. end;
  27.  
  28. begin
  29.   RequireDerivedFormResource := True;
  30.   Application.Scaled := True;
  31.   Application.Initialize;
  32.   Application.CreateForm(TForm1, Form1);
  33.   Application.OnActivate := @TDummy(Nil).EventHandler; // Supplying an invalid Self
  34.   Application.Run;
  35. end.
  36.  
Here an invalid Self was passed for the handler (line 33) and when called, line 25 should trigger an AV. Because of the precondition on line 22 it won't.

You can figure out how to validate Self on line 22, e.g. keeping track of freed instances and search Self amongst them, and when the validation fails then to write log or something. You may even dump the stack trace there.

This seems to be sufficient sure for me.
You can never be sure that the error isn't somewhere else. You can only be sure that it's no longer at that particular place.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

egsuh

  • Hero Member
  • *****
  • Posts: 1694
I had the same issue. I moved the class var to universal variable (which is declared in the interface section as variable, not within any component/class), which is actually an interface, and the problem disappeared. 

Hartmut

  • Hero Member
  • *****
  • Posts: 1007
Thanks alpine for your post and your demo, but we have misunderstood. The Event-Handler for 'Application.OnActivate' is only changed very temporarily only during the runtime of this certain procedure in a common unit and now is safely restored before the procedure exits.

alpine

  • Hero Member
  • *****
  • Posts: 1410
Thanks alpine for your post and your demo, but we have misunderstood. The Event-Handler for 'Application.OnActivate' is only changed very temporarily only during the runtime of this certain procedure in a common unit and now is safely restored before the procedure exits.
Does this mean that the common procedure is written incorrectly? You claim that it is possible for Application.OnActivate() to fire after the internal class was freed (multi-threaded?) while the procedure wasn't yet exited? Оtherwise you can just close the call in try...finally..end and finally to restore the Application.OnActivate in the place of the call and without resorting to OnDestroy.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

jamie

  • Hero Member
  • *****
  • Posts: 7306
Maybe not directly related but what could help a lot of these problems is if we had an onrun in the application class that way initializing code can be done when all the forms that are in the auto create list are completely created so that way all these forms could talk to each other without issues.

OnRun event

Jamie
The only true wisdom is knowing you know nothing

Hartmut

  • Hero Member
  • *****
  • Posts: 1007
Does this mean that the common procedure is written incorrectly? You claim that it is possible for Application.OnActivate() to fire after the internal class was freed (multi-threaded?) while the procedure wasn't yet exited?
As I wrote: we have misunderstood. The common procedure had been incorrectly - now it is fixed!

Quote
Otherwise you can just close the call in try...finally..end
I already had used try/finally. I only had forgotten to restore 'Application.OnActivate'. Now it is fixed and everything is ok!

 

TinyPortal © 2005-2018