Recent

Author Topic: Recreating Application object during runtime  (Read 3635 times)

furious programming

  • Hero Member
  • *****
  • Posts: 852
Re: Recreating Application object during runtime
« Reply #15 on: April 25, 2020, 01:43:59 am »
Actually just write an onClose event for the main form and set the CloseAction var parameter to caFree. That will free the form and since the application is registered to be called when the mainform is destroyed it will set the mainform property to nill.

I modified my test application and applied your tip, but it doesn't work. I generated OnClose events for all forms and assigned caFree to CloseAction, but the second call to the Run method ends immediately and LoginForm appears again. So the login form is not closed and must be freed by Application.MainForm.Free.

Thanks for the code snippet. IMO something like this should be implemented in TApplication class.
« Last Edit: April 25, 2020, 01:48:21 am by furious programming »
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
Re: Recreating Application object during runtime
« Reply #16 on: April 25, 2020, 01:00:36 pm »
my friend ask me today about implementation a logging system in the application, that shows appropriate main form depends on the user privileges (regular user or admin).
No need for run time decision what main form is. It is much simpler to use one main form and 2 frames, and then in runtime decide which frame to show in main form. Depending on your use case, things might be even simpler then that if main form can be login dialogue.

For logging you might want to look at https://github.com/blikblum/multilog. It can even log multiple threads to the same memo or file.
« Last Edit: April 25, 2020, 01:06:22 pm by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

furious programming

  • Hero Member
  • *****
  • Posts: 852
Re: Recreating Application object during runtime
« Reply #17 on: April 25, 2020, 02:12:15 pm »
@avra: of course. However, the logging system was only a first example — there are a lot of different reasons to use Application multiple times, because why not? There will always be a use of such a scheme, for simple applications, but also for more sophisticated ones. 8)
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Recreating Application object during runtime
« Reply #18 on: April 25, 2020, 03:03:07 pm »
I just tested something like this and the control flow is correct, no memory leaks. However, when I run application under debugger (standard run by F9 key), I get SIGSEGV after closing the OtherForm (see attachment).

So, it is safe and somewhere in the TApplication is a bug, or is this UB? I'm just curious. 8)

No this is not safe as some code somewhere might have stored a reference to the TApplication instance or some code is still running inside the instance. If you simply free it the code will now access invalid memory. There is no way to solve this in a clean way.

furious programming

  • Hero Member
  • *****
  • Posts: 852
Re: Recreating Application object during runtime
« Reply #19 on: April 25, 2020, 05:14:03 pm »
There is no way to solve this in a clean way.

I also talked to various Polish developers and one of them found a similar structure in a large project developed in Borland C++ Builder 2009, which he worked on:

Code: C++  [Select][+][-]
  1. Application->Initialize();
  2. Application->MainFormOnTaskBar = true;
  3. Application->CreateForm(__classid(TForm1), &Form1);
  4. Application->Run();
  5.  
  6. delete Application;
  7. Application = new TApplication(NULL);
  8. Application->Initialize();
  9. Application->MainFormOnTaskBar = true;
  10. Application->CreateForm(__classid(TForm2), &Form2);
  11. Application->Run();

So Borland apparently has the TApplication class written in such a way that it is actually independent, because the above code works fine even under the debugger.
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Recreating Application object during runtime
« Reply #20 on: April 25, 2020, 05:30:10 pm »
So Borland apparently has the TApplication class written in such a way that it is actually independent, because the above code works fine even under the debugger.

Even if Borland has written the TApplication class this way, as soon as a third party component stores a reference to the Application instance you're done for. Or if you have an application that uses threads and some thread function is inside the code of TApplication and wants to access a field after the application instance has been freed.

furious programming

  • Hero Member
  • *****
  • Posts: 852
Re: Recreating Application object during runtime
« Reply #21 on: April 25, 2020, 07:44:27 pm »
Even if Borland has written the TApplication class this way, as soon as a third party component stores a reference to the Application instance you're done for.

Of course, but storing reference to the global object, which exists during the whole session IMO has no sense. Well, unless you have several instances of this class. :D

Ok, I'm just kidding.
« Last Edit: April 25, 2020, 07:55:31 pm by furious programming »
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

eljo

  • Sr. Member
  • ****
  • Posts: 468
Re: Recreating Application object during runtime
« Reply #22 on: April 25, 2020, 08:04:52 pm »
So Borland apparently has the TApplication class written in such a way that it is actually independent, because the above code works fine even under the debugger.

Even if Borland has written the TApplication class this way, as soon as a third party component stores a reference to the Application instance you're done for. Or if you have an application that uses threads and some thread function is inside the code of TApplication and wants to access a field after the application instance has been freed.
yeah but then I'm responsible of being stupid and I have the chance to correct it. As things are now you are being stupid and I can't do anything about it.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9791
  • Debugger - SynEdit - and more
    • wiki
Re: Recreating Application object during runtime
« Reply #23 on: April 25, 2020, 08:33:16 pm »
Of course, but storing reference to the global object, which exists during the whole session IMO has no sense. Well, unless you have several instances of this class. :D
Not necessarily
Code: Pascal  [Select][+][-]
  1. MessageBoxProc := @Application.MessageBox;
Totally plausible, if you have other ways to show messageboxes (to be selected, depending on whatever your code does).

MessageBoxProc includes a reference to the object.


 

TinyPortal © 2005-2018