raise 문
raise 문
raise 문은 예외(exception)를 발생시키는 데 사용해요. 일부러 오류 상황을 만들 때 이를 재발생시키거나, 새 예외 객체를 던지는 두 가지 방식으로 쓰입니다.
출처: 문서
본문
raise 문의 형태는 다음과 같습니다.
Raise statement → raise [exception instance [at exception address]]
Exception address → at address expression
이 문장은 예외를 발생시켜요. 지정되면, 예외 인스턴스는 어떤 클래스의 초기화된 인스턴스여야 하며, 이것이 raise 타입이 됩니다. 예외 주소와 프레임은 선택적이에요. 지정하지 않으면 컴파일러가 주소를 직접 제공합니다.
예외 인스턴스가 생략되면 현재 예외가 다시 발생(재발생)돼요. 이 구성은 예외 처리 블록 안에서만 사용할 수 있습니다. (자세한 내용은 아래 참고)
주의: 예외 블록 이후로 제어는 결코 돌아오지 않아요. 스택이 풀리면서(stack unwinding) 만나는 첫 번째 try...finally 또는 try...except 문으로 제어가 이동합니다. 그런 문장이 없으면, Free Pascal 런타임 라이브러리는 런타임 오류 217을 생성해요. (17.5절 참고) 예외 주소는 기본 예외 처리 루틴이 출력합니다.
예시: 0으로 나누기
다음 나눗셈은 분모가 0인지 확인하고, 0이면 EDivException 타입의 예외를 발생시켜요.
Type EDivException = Class(Exception);
Function DoDiv (X,Y : Longint) : Integer;
begin
If Y=0 then
Raise EDivException.Create ('Division by Zero would occur');
Result := X Div Y;
end;
Exception 클래스는 RTL의 Sysutils 유닛에 정의되어 있어요. (17.5절 참고)
주의: 코드 전반에서 Exception 클래스가 예외의 기본 클래스로 쓰이지만, 이것은 문서화되지 않은 합의일 뿐이에요. 예외 클래스는 어떤 타입이든 될 수 있고 Exception 클래스의 하위 클래스일 필요는 없습니다. 물론 대부분의 코드는 예외 클래스가 Exception에서 상속된다는 암묵적 합의에 의존하고 있어요.
예: 스택에서 보고 루틴 생략하기
다음 코드는 예외 처리기에서 보여지는 스택에서 오류 보고 루틴을 생략하는 방법을 보여줍니다.
{$mode objfpc}
uses sysutils;
procedure error(Const msg : string);
begin
raise exception.create(Msg) at
get_caller_addr(get_frame),
get_caller_frame(get_frame);
end;
procedure test2;
begin
error('Error');
end;
begin
test2;
end.
실행하면 이 프로그램은 다음과 같은 백트레이스(backtrace)를 보여줍니다.
An unhandled exception occurred at $00000000004002D3 :
Exception : Error
$00000000004002D3 line 15 of testme.pp
$00000000004002E6 line 19 of testme.pp
15행은 실제로 예외를 발생시킨 Error가 아니라 프로시저 Test2 안에 있습니다.
더 알아보기
- Free Pascal Reference Manual 17장 예외 처리
- try...except 문
- Free Pascal Reference Manual 17.5절 예외 클래스