Sobre try..finally
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:
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´?
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
Curtidas 0
Respostas

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.
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
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
02/10/2006
Esse código em particular não precisa do try..finally... Eu faria assim...
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......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.
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);
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
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
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
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?
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
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