1

i have the code as follows:

begin
  Application.Initialize;
  Application.Title := 'Controle Bancário';
  Application.CreateForm(T_DMEstagio, _DMEstagio);
  Application.CreateForm(T_frmLogin, _frmLogin);
  if (_frmLogin.ShowModal = 1) then
    begin
      FreeAndNil(_frmLogin);
      Application.CreateForm(T_frmPrincipal, _frmPrincipal);
      Application.Run;
    end;
    _DMEstagio.Free;

end.

If I DONT explicitly free the DM as I did in the code, I get an Access Violation Exception, but in another application that the code is like this:

begin
    Application.Initialize;
    Application.Title := ' > Sistema de Gestão Comercial <';
    if HPrevInst = 0 then
    begin
      Application.CreateForm(TFrmPrincipal, FrmPrincipal);
      Application.CreateForm(TIBDM, IBDM);
      Application.Run;
    end ;
end.

I dont have to free the DM and i dont get any exception. Why is that?

  • The answer lies in the code that you did not show. Presumably somewhere in the DM code. Cut this down to an MCVE. Or even use the debugger to identify where the AV occurs. – David Heffernan May 21 '15 at 15:05
  • Answer to your question "When do I need to free Data Module/Form created by Application?" is never. Why you are having AV is completely different question and answer is somewhere in your other code... – Dalija Prasnikar May 21 '15 at 16:23
  • There is no code in my DM yet, and for the problem to happen i dont even have to enter in my main form, if I close the _frmLogin as soon as it appears, I get the error already. If I debug it, I get the AV when trying to destroy RxHook, which I dont think its correct.. – Cristian Trein May 21 '15 at 19:05
  • @DalijaPrasnikar I think I discovered what it is. When I indeed enter on my main form I dont get any AV, If you look at my code you can see that `Application.Run;` is only activated when I do access the main form, BUT if i put this code before my `if` I get a different error `cannot make visible a modal form`. What should I do now? – Cristian Trein May 21 '15 at 19:22
  • @DavidHeffernan The problem appears to be that `Application.Run` is only executed if the login and password are correct. So far, the easiest way to deal with it is to indeed free the DM. Any thoughts? – Cristian Trein May 22 '15 at 12:21
  • Personally I'd stop using `Application.CreateForm`. Call it exactly once. For the main form. Do you need to create the DM if the login fails? If not, don't. – David Heffernan May 22 '15 at 12:23
  • I have to, since the login form looks in the DB to validate the user or not.. – Cristian Trein May 22 '15 at 12:25

1 Answers1

0

Answer to your question

"When do I need to free a Data Module created by the Application?"

is never.

All data modules and/or forms created with Application.CreateForm method will be owned by Application and automatically handled.


But as it seems, you issues are not related to automatic destruction process. Following code should resolve your issues as some components and classes need application to complete its full initialization/running cycle in order to destroy gracefully. It is possible that RXHook is one of them.

begin
  Application.Initialize;
  Application.Title := 'Controle Bancário';
  Application.ShowMainForm := false;
  Application.CreateForm(T_DMEstagio, _DMEstagio);
  Application.CreateForm(T_frmLogin, _frmLogin);
  if (_frmLogin.ShowModal = 1) then
    begin
      FreeAndNil(_frmLogin);
      Application.ShowMainForm := true;
      Application.CreateForm(T_frmPrincipal, _frmPrincipal);
    end
  else Application.Terminate;
  Application.Run;
end.

So what is exactly happening in above code?

You are trying to show login form and depending on login result proceed with running your application or terminate it.

It is important to note that first form you create will become Application.MainForm, if that form is released before Application.Run executes Application.MainForm will be set back to nil. That will ensure that next created form can become main form.

In your case that means that _frmLogin will be set as your Application.MainForm. If login is successful, it will be released and _frmPrincipal will take over. But if the login is not successful _frmLogin will still be Application.MainForm when Application.Run is executed and will be shown again.

This is where Application.ShowMainForm comes into place. When it is set to false Application.Run will just run without showing any forms. In your case it will prevent _frmLogin to reappear again. Of course, on successful login you want to set Application.ShowMainForm back to true to ensure normal application startup.

Calling Application.Terminate in case of unsuccessful login will ensure that your application exits application main message loop that will start with call to Application.Run and terminate gracefully.

Dalija Prasnikar
  • 27,212
  • 44
  • 82
  • 159
  • Almost. If I use `Application.Run` in the end as in your example, if I just execute the app and try to close it, I have to close it twice. If I use the `Application.ShowMainForm` and try to do the same when I close the app, it keeps executing, but I cannot see the window anymore. What I did for now is to put `Application.Terminate` on the `onClose` event of the Login Form. It's working, but maybe there is a more elegant aprocach that i'm missing. – Cristian Trein May 21 '15 at 21:27
  • You have to use above code snippet as-is. All parts are important. If you omit some you will get wrong behavior. Do not put `Application.Terminate` in `onClose` event and use above code without modifications and then tell me what are the issues you are facing. – Dalija Prasnikar May 22 '15 at 07:47
  • Sorry to not explain it well. When I use the code as in your example, if I try to close te login form, the program keeps running, but I cannot see the login form anymore. – Cristian Trein May 22 '15 at 12:18
  • If you have `Application.Terminate` like in above example, then problem has to be in your login form. How do you close it? Can you post some code? – Dalija Prasnikar May 22 '15 at 13:40
  • Ouch, must say that I wasnt using `Application.Terminate` because I thought it would close my application in case I failed at first Login attempt. My bad. Now it's working perfectly, Thanks Sir! – Cristian Trein May 22 '15 at 14:34