Fórum Sobre try..finally #330484

02/10/2006

0

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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

Responder

Posts

02/10/2006

Massuda

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.


Responder

Gostei + 0

02/10/2006

Djorius

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.


Responder

Gostei + 0

02/10/2006

Massuda

Esse código em particular não precisa do try..finally... Eu faria assim...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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...
1
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.


Responder

Gostei + 0

02/10/2006

Djorius

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


Responder

Gostei + 0

02/10/2006

Massuda

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.


Responder

Gostei + 0

02/10/2006

Micheus

[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?
1
2
3
4
5
6
7
8
9
10
11
12
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
...



Responder

Gostei + 0

02/10/2006

Massuda

...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...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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;



Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar