1

I am writing an error handler that tried to fix or mitigate the error. If the mitigation code errors I want to ignore the mitigation error and raise the original error. This is the error handler I have written.

try
  // <Normal code>
  raise Exception.Create('Original error');
except
  on E: Exception do
  try
    // <Attempt to mitigate the error>  // If successful will continue without an exception
    raise Exception.Create('Mitigation error'); 
  except
    raise E;  // Mitigation failed, raise original error
  end;
end;

The above does not work. When the mitigation exception triggers the application descends into a chaos of invalid pointers.

Does anyone know how to do this?

2
  • 1
    What is the purpose of nested try..except? The issue is that you use raise E to re-raise the original exception. This is what you should do instead: on E: Exception do if not TryMitigate(E) then raise;. Commented May 21, 2020 at 7:47
  • @PeterWolf The point is, I guess, that the mitigation can raise an exception Commented May 21, 2020 at 7:53

1 Answer 1

2
try
  // <Normal code>
  raise Exception.Create('Original error');
except
  on E: Exception do
  try
    // <Attempt to mitigate the error>  // If successful will continue without an exception
    raise Exception.Create('Mitigation error'); 
  except
    raise E;  // Mitigation failed, raise original error
  end;
end;

Once you handle an exception, it will be destroyed at the end of the except block which handles it. However, you do raise E which propagates the exception beyond that block, and beyond the end of its life.

If you wish to re-raise an exception, and thus prolong its life beyond the block which handles it, then you need to use different syntax, unadorned raise. However, you cannot do that inside the nested except block since that would refer to the mitigation error. Instead you need to write raise in the outer except block:

procedure Foo;
var
  MitigationSucceeded: Boolean;
begin
  try
    // <Normal code>
    raise Exception.Create('Original error');
  except
    on E: Exception do
    begin
      try
        MitigationSucceeded := True;
        // <Attempt to mitigate the error>  // If successful will continue without an exception
        raise Exception.Create('Mitigation error');
      except
        // using raise here would refer to mitigation error ...
        MitigationSucceeded := False;
      end;

      if not MitigationSucceeded then
        // ... but used here it is the original error
        raise;
    end;
  end;
end;
Sign up to request clarification or add additional context in comments.

1 Comment

Perfect. Thank-you David.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.