delphimemory-managementdatamodule

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


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?


Solution

  • 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.