Esperando no complicar mas las ideas voy aclarando algunas dudas;
try crea una instruccion de "
salto en caso de error", obviamente "salta" a la primera instruccion de su respectivo
finally ejecutando su contenido hasta
end; cada try genera un salto distinto para permitir al desarrollador un control más especifico para cada posible error, por ello desde el punto de vista de compilación los casos anidado y "compacto" generan un codigo binario distinto.
Si la excepción es generada
dentro del constructor, el valor retornado por el mismo es nulo (puesto que falló durante la creación de la nueva
instancia), por ende, el llamado al método en memoria 0
.Destroy ó 0
.Free generan el mismo error de acceso a una zona de memoria
vacía.
Código Delphi
[-]uses SysUtils; {$apptype console}
var Saved: procedure;
procedure OnExit;
begin
ReadLn; Saved;
end;
type
TThrow = class procedure Throw;
constructor Create;
destructor Destroy; override;
end;
procedure TThrow.Throw; asm dd 0F4F6E432h end;
constructor TThrow.Create;
begin
inherited;
WriteLn(Self.ClassName + '();'); end;
destructor TThrow.Destroy;
begin
WriteLn('~' + Self.ClassName + '();'); inherited;
end;
type
TFirst = class(TThrow); TSecond = class(TThrow);
var
a, b: TThrow;
begin
@Saved := ExitProc;
ExitProc := @OnExit;
{$define anidado}
{$ifdef anidado}
try
a := TFirst.Create;
a.Throw;
try
b := TSecond.Create;
b.Throw;
finally
b.Destroy;
end;
finally
a.Destroy;
end;
{$else}
try
a := TFirst.Create;
a.Throw;
b := TSecond.Create;
b.Throw;
finally
a.Destroy;
b.Destroy; end;
{$endif}
end.
En el anterior ejemplo he "sacado" la generación de la excepción del constructor, para demostrar que entre el codigo inicial de Roman y último no es relevante la construcción del objeto, si no el orden construcción/excepción de los objetos.
En el caso anidado el control es mayor y más estructurado, como resultado obtenemos un
EDivByZero que era justamente lo esperado... lo que difiere al comentar la directiva de precompilación, " // {$define anidado}" obteniendo un
EAccessViolation al intentar destruir un objeto "inexistente".
Podriamos hacer otro ejemplo no OO, talvez ordenes de apertura y cerrado de archivos de paginación... en tal caso obtendriamos un resultado que al igual que en el ejemplo depende de la estructura del codigo.
Saludos