Sobre try..finally

Delphi

02/10/2006

Queria saber qual a finalidade do try..finally no delphi. Estava vendo um código de exemplo que vem com uma DLL para validação de Inscrição Estadual. Veja o código:

procedure TfrmInscDv.btnCalculaClick(Sender: TObject);
var IRet, IOk, IErro, IPar    : Integer;
    LibHandle                 : THandle;
    ConsisteInscricaoEstadual : TConsisteInscricaoEstadual;
begin
   try
      LibHandle :=  LoadLibrary (PChar (Trim (´DllInscE32.Dll´)));
      if  LibHandle <=  HINSTANCE_ERROR then
      raise Exception.Create (´Dll não carregada´);
      //
      @ConsisteInscricaoEstadual  :=  GetProcAddress (LibHandle,´ConsisteInscricaoEstadual´);
      if  @ConsisteInscricaoEstadual  = nil then
      raise Exception.Create(´Entrypoint Download não encontrado na Dll´);
      //
      IRet := ConsisteInscricaoEstadual (edtInscricao.Text,edtUF.Text);
      if Iret = 0 then
      MessageDlg (´Inscrição válida para ´+edtUf.Text,mtInformation,[mbOk],0)
      else if Iret = 1 then
      MessageDlg (´Inscrição inválida para ´+edtUf.Text,mtError,[mbOk],0)
      else
      MessageDlg (´Parâmetros inválidos´,mtError,[mbOk],0);
      edtInscricao.SetFocus;
   finally
      FreeLibrary (LibHandle);
   end;
end;


minha dúvida é a seguinte: Se o ´FreeLibrary(LibHandle);´ estivesse logo após o ´edtInscricao.SetFocus´ ele não seria executado da mesma forma que estando dentro do finally? Que seria a diferença se não tivesse esse try..finally e o ´FreeLibrary´ estivesse depois da última linha que atualmente está dentro do ´try´?


Djorius

Djorius

Curtidas 0

Respostas

Massuda

Massuda

02/10/2006

Esse código não seria o que eu usaria, mas com relação a sua dúvida...

O FreeLibrary sempre será executado, mesmo no caso da DLL não ser encontrada ou qualquer outro problema no bloco que vai do try até o finally.

Se o FreeLibrary estivesse na linha imediatamente antes do finally, a DLL só seria descarregada quando tudo desse certo dentro do bloco que vai do try até o finally; nos outros casos, ela permaneceria carregada pelo seu programa.


GOSTEI 0
Djorius

Djorius

02/10/2006

Esse código não seria o que eu usaria,


Se refere ao modo como a dll está sendo carregada no código? Se for, eu também não gosto de usar assim e não pretendo usar esse código dessa maneira. Foi só pra exemplificar mesmo.

Agora, deixa eu ver se entendi. Se aquele segundo ´raise´ fosse executado a dll continuaria carregada em memória. Deixando o FreeLibrary dentro do Finally ela será descarregada depois do raise. é isso?

grato pela ajuda.


GOSTEI 0
Massuda

Massuda

02/10/2006

Esse código em particular não precisa do try..finally... Eu faria assim...
LibHandle :=  LoadLibrary (PChar (Trim (´DllInscE32.Dll´))); 
if  LibHandle >  HINSTANCE_ERROR then 

  ConsisteInscricaoEstadual  :=  GetProcAddress(LibHandle,´ConsisteInscricaoEstadual´); 
  if Assigned(ConsisteInscricaoEstadual) then begin

    IRet := ConsisteInscricaoEstadual (edtInscricao.Text,edtUF.Text); 
    if Iret = 0 then 
      MessageDlg (´Inscrição válida para ´+edtUf.Text,mtInformation,[mbOk],0) 
    else if Iret = 1 then 
      MessageDlg (´Inscrição inválida para ´+edtUf.Text,mtError,[mbOk],0) 
    else 
      MessageDlg (´Parâmetros inválidos´,mtError,[mbOk],0); 

    if edtInscricao.CanFocus then
      edtInscricao.SetFocus; 

    FreeLibrary (LibHandle); 
  end
  else begin
    // não achou "ConsisteInscricaoEstadual" na DLL
  end;
end
else begin
  // não conseguiu carregar a DLL
end;


Mas tem um problema em potencial: se a DLL não foi feita em Delphi e nem usar a DLL BorlandMM.DLL, então esta linha...
IRet := ConsisteInscricaoEstadual (edtInscricao.Text,edtUF.Text);
...pode gerar problemas, pois apenas DLLs feitas em Delphi com ShareMem no uses (que faz carregar a BorlandMM.DLL) sabem lidar com strings do Delphi.

Agora, deixa eu ver se entendi. Se aquele segundo ´raise´ fosse executado a dll continuaria carregada em memória. Deixando o FreeLibrary dentro do Finally ela será descarregada depois do raise. é isso?
Sim.


GOSTEI 0
Djorius

Djorius

02/10/2006

Uma outra dúvida que surgiu agora: nesse código, se eu trocar finally por except o resultado é o mesmo?


GOSTEI 0
Massuda

Massuda

02/10/2006

Uma outra dúvida que surgiu agora: nesse código, se eu trocar finally por except o resultado é o mesmo?
Não porque a parte entre o except e o end [b:fe7ad9de65]só[/b:fe7ad9de65] é executada em caso de erro. No seu exemplo, quando tudo desse certo, a DLL não seria descarregada pelo programa.


GOSTEI 0
Micheus

Micheus

02/10/2006

[b:3f04860f5b]Massuda[/b:3f04860f5b], mas se vc chama FreeLibrary (LibHandle) apenas se a função for encontrada (ConsisteInscricaoEstadual), que garantias tenho, quando a função não existir ou for digitada incorretamente, de que a biblioteca será liberada da memória?

Não seria mais apropriado deixar a chamada a FreeLibrary (LibHandle) após o end da instrução else?
LibHandle :=  LoadLibrary (PChar (Trim (´DllInscE32.Dll´)));
if  LibHandle >  HINSTANCE_ERROR then begin
  ConsisteInscricaoEstadual  :=  GetProcAddress(LibHandle,´ConsisteInscricaoEstadual´);
  if Assigned(ConsisteInscricaoEstadual) then begin
    ...
  else begin
    // não achou "ConsisteInscricaoEstadual" na DLL
  end;
  FreeLibrary (LibHandle);  // ***
end
else begin
...



GOSTEI 0
Massuda

Massuda

02/10/2006

...se vc chama FreeLibrary (LibHandle) apenas se a função for encontrada (ConsisteInscricaoEstadual)...
Tem razão, o FreeLibrary está no lugar errado. O correto seria...
LibHandle :=  LoadLibrary (PChar (Trim (´DllInscE32.Dll´))); 
if  LibHandle >  HINSTANCE_ERROR then 

  ConsisteInscricaoEstadual  :=  GetProcAddress(...
  if Assigned(ConsisteInscricaoEstadual) then begin 

    IRet := ConsisteInscricaoEstadual (edtInscricao.Text,edtUF.Text); 
    if Iret = 0 then 
      MessageDlg (´Inscrição válida para ´...) 
    else if Iret = 1 then 
      MessageDlg (´Inscrição inválida para ´...) 
    else 
      MessageDlg (´Parâmetros inválidos´,mtError,[mbOk],0); 

    if edtInscricao.CanFocus then 
      edtInscricao.SetFocus; 
  end 
  else begin 
    // não achou "ConsisteInscricaoEstadual" na DLL 
  end; 

  FreeLibrary (LibHandle); 
end 
else begin 
  // não conseguiu carregar a DLL 
end;



GOSTEI 0
POSTAR