Chapter 11 – 예외 처리 Outline 11.1 설계 쟁점 11.2 Pl/I의 예외 처리 11.3 Ada의 예외 처리 11.1 설계 쟁점 11.2 Pl/I의 예외 처리 11.3 Ada의 예외 처리 11.4 C++의 예외 처리 11.5 java의 예외 처리
11.1 설계 쟁점 Procedure의 종료 해결 방법 return (정상), goto overflow, underflow, range error - system interrupt EOF 등 예외조건 (예상 가능한 조건) 해결 방법 예외조건 제어 불가능 언어 오류 시 약속된 값 반환 - Programmer 매번 check 오류 처리 루틴으로 즉시 제어 이동 (정상제어 파괴) 예외조건 제어 가능 언어 사용자 제어 가능 PL/I : 최초 제공 언어 MESA, CLU, Ada, C++, Java : 우아한 방법 제공
11.1 설계 쟁점 예외 처리 프로시저들 사이의 정보 교환 프로시저들간의 특별한 제어 허용 예외란 오류가 아님 초기 예외 처리 일반적인 호출 반환과 다름 프로시저들간의 특별한 제어 허용 예외란 오류가 아님 초기 예외 처리 Hardware interrupt routine을 사용 system에서 제공 : 종류, 처리 루틴 예외 처리시 고려해야 할 쟁점들 어떤 프로시저가 발생된 예외를 처리할 것인가? 예외 처리 후 예외 발생 프로시저의 활성화 지속 여부?
11.1 설계 쟁점 어떤 프로시저가 발생된 예외를 처리? 활성화된 procedure중에서 결정하는 방법
11.1 설계 쟁점 예외 처리의 주요 쟁점 System interrupt 접근 방법이 제공되었는가? 사용자 정의 예외가 가능한가? 이 예외를 어떻게 발생시키는가? 가능 예외(enable exception)의 영역 규칙은 무엇인가? 예외 처리(exception handler)의 영역은 어디인가? 예외를 발생시킨 프로시저를 실행 재개시키는가 종결시키는가? 발생된 예외의 전파(propagation)는 어떻게 되는가? 한 예외에 매개 변수를 사용하여 다양화 시킬 수 있는가? (예기치 않았던) 모든 예외를 한번에 자동 처리할 수 있는가? 예외 처리 루틴에서 예외를 발생 시킬 수 있는가? 이 때 후속 처리는?
11.2 PL/I의 예외 처리 시스템 제공 on condition(조건)만 사용 가능 수치계산 condition : default enable 1. CONVERSION 2. FIXEDOVERFLOW 3. OVERFLOW 4. UNDERFLOW 5. ZERODIVIDE Program test condition : default disable 6. SIZE 7. SUBSCRIPTRAGE 8. STRINGRANGE 9. CHECK 10.AREAR 입출력 condition : always enable 11. ATTENSION 12. CONDITION 13. ENDFILE 14. ENDPAGE 15. ERROR 16. FINISH 17. KEY 18. NAME 19. PENDING 20. RECORD 21. TRANSMIT 22. UNDEFINITEFILE
11.2 PL/I의 예외 처리 예외 조건 상태 제어 (가능/불능) enable 선언 : condition 이름 (prefix 사용) disable 선언 : NO + condition 이름 (prefix 사용) 예) (NOUNDERFLOW, STRINGRANGE) disable enable 예외 조건 영역 (scope) 문장 - 한 문장만이 예외 조건 영역 if문 - condition field만 영역 적용 procedure, begin -end - 해당 블록 (inner 블록은 상속)
11.2 PL/I의 예외 처리 예외 처리 루틴 (Exception Handler) 예외 처리 수행 후 (제어 이동) 표준 시스템 예외 처리 루틴 : default - user overruling 가능 예외 처리 루틴 사용자 정의 ON condition-name <on-unit> <on-unit> : 사용자 정의 예외 처리 루틴(문장 또는 블록) 예외 처리 수행 후 (제어 이동) 예외를 발생 시킨 문장 예외를 발생 시킨 문장 다음 문장 handler에서 별도로 분기 가능 예외 발생 (enable 상태 예외만 가능) 시스템에서 자동 발생 사용자 발생 SIGNAL condition-name SIGNAL condition-name (identifier) : 사용자 정의 예외 취급 가능
11.2 PL/I의 예외 처리 1 TEST:PROCEDURE OPTIONS(MAIN); 2 DECLARE (PERSON , GRADE) FIXED; 3 DECLARE LAST FIXED INIT(0); 4 DECLARE SUMMARY(1:50 , 0:100) FIXED; 5 ON ENDPAGE(SYSPRINT) /* 오류 메시지 리스트를 위한 제목 인쇄 */ 6 BEGIN PUTPAGE; PUT LIST(' ' , 'LIST ERROR DATA'); END; 7 ON SUBSCRIPTRANGE BEGIN 8 IF LAST = 0 THEN SIGNAL ENDPAGE(SYSPRINT); 9 /* 오류가 첫 번째로 발견되면 오류 리스트의 제목 인쇄 */ 10 IF I NOT = LAST THEN /* 새로운 경우를 검사 */ 11 PUT SKIP DATA(I , PERSON , GRADE); 12 LAST = I 13 END; 14 ON ENDFILE(SYSIN) BEGIN; 15 PUT PAGE LIST(' ' , ' ' , `OUTPUT FOR CLASS'); 16 PUT SKIP LIST(' ' , ' ' , 'SUMMARY'); 17 PUT SKIP(3) LIST(SUMMARY); 18 IF LAST NOT = 0 THEN PUT SKIP(4) LIST 19 ('SOME DATA IS INCOMPLETE, SEE OUTPUT'); 20 END; 21 SUMMARY = 0; 22 A:DO I = 1 BY 1; 23 GET LIST(PERSON , GRADE); 24 SUMMARY(PERSON , GRADE) = SUMMARY(PERSON , GRADE) + GRADE; 25 END A; 26 END TEST;
11.2 PL/I의 예외 처리 PL/I ON 문의 문제점 예외 발생 비지역 테이블로 분기 동작 발생 가능 어떤 handler가 처리(dynamic link) 정적 영역을 벗어나므로 예측 불허 해결책 : 예외 처리 루틴 제공 (해당 프로그램 내) 비지역 테이블로 분기 동작 발생 가능 open된 file들을 close하지 못함 계산형 예외 조건 불일치 OVERFLOW, SUBSCRIPTRANGE : 반환 불허 UNDERFLOW, STRINGRANGE : 반환 disable condition 조건을 검사하지 않을 뿐 조건 발생 : 오류로 취급되어 나머지 프로그램 실행 미정의
11.3 Ada의 예외 처리 Steelman Requirements - Ada의 예외 처리에 대한 명세 예외 처리 실행 후, 발생 블록 실행 재개 안 함 다수의 미리 정의된(predefined) 예외 제공 - 시스템 환경 Ada의 미리 정의된 예외 종류 CONSTRAINT-ERROR : 영역, 첨자, 열거형 자료 등에 대한 제한 이탈, null 접근 시 NUMERIC-ERROR : 연산 결과가 영역을 벗어날 때 SELECT-ERROR : select문에서 택일 조건 모두가 만족되지 않을 때 STORAGE-ERROR : 기억 장소를 할당할 수 없을 때 TASKING-ERROR : 태스크간에 통신 할 때
11.3 Ada의 예외 처리 Ada의 사용자 정의 예외 exception 선언문 예) BAD_FORMAT, TIMEOUT, XXX : exception 예외 발생 자동 발생 (시스템 정의 예외) 사용자 발생 (raise문 이용) 예) raise TIMEOUT
11.3 Ada의 예외 처리 예외 처리 루틴 예외 처리 순서 시스템 제공 예외 처리 사용자 예외 처리 루틴 재 정의 가능 (우선) 사용자 정의 예외 처리 루틴 작성 형태 <exception-handler> ::= when <exception-choice>{|<exception-choice>} => <statements> <exception-choice> ::= <exception-name> | others 예외 처리 순서 예외 발생 프로그램 예외 처리 루틴 존재 해당 루틴에서 처리 예외 처리 루틴 부재 caller로 예외 전파 (dynamic) 예외 처리 후 제어는 예외 처리 루틴이 제공된 프로그램의 caller로 반환
< Ada 예외 처리 루틴 구문 예 > begin -- this is a sequence of statements exception when NUMERIC_ERROR => -- 수치 오류를 처리하는 작업 when BAD_FORMAT => -- 어떤 예외 처리 작업 when others => -- 위 두 예외를 제외한 모든 예외를 처리하는 작업 end;
11.3 Ada의 예외 처리 < Ada 예외 처리 예 > 1 procedure P is 2 BAD-FORMAT:exception; 3 procedure Q is 4 begin 5 . . . 6 if S /='' then raise BAD_FORMAT;end if; 7 . . . 8 end Q; 9 procedure R is 10 begin 11 Q; 12 exception when BAD_FORMAT => -- handler body 1 13 end R; 14 begin 15 R; 16 Q; 17 exception when BAD_FORMAT => -- handler body 2 18 end P;
11.3 Ada의 예외 처리 예외사항 발생 예외 사항의 전파 예외사항이 발생되었지만 해당 예외처리기가 없는 경우는 호출한 상위 프로그램으로 제어가 넘어감 예외사항 발생 예외의 전파 (Propagation of Exception)
11.3 Ada의 예외 처리 < Ada 예외 전파 사용 예 > 1 procedure A is 2 procedure B is 3 FLOPPED :exception; 4 begin 5 -- sequence of statements 6 exception when FLOPPED => raise end; begin B; exception when others => -- handle FLOPPED if possible else raise;
< Ada에서의 다양한 예외들의 사용 예 > 1 procedure DOSOMETHING is 2 HANDLE_ERROR:exception; 3 begin 4 -- perform some set of actions 5 exception 6 when HANDLE_ERROR => -- error handing code 7 end; 8 end DOSOMETHING; 9 function SECURE_DIVIDE(X , Y:REAL) return REAL is 10 begin 11 return X / Y; 12 exception 13 when NUMERIC_ERROR => return 0; 14 end SECURE_DIVIDE; 15 procedure COPYOVER is 16 begin 17 OPEN(INFILE); 18 OPEN(OUTFILE); 19 loop 20 GET(INFILE , CHARACTER); 21 PUT(OUTFILE , CHARACTER); 22 end loop; 23 exception 24 when END_OF_FILE => 25 PUT(OUTFILE , EOF); 26 CLOSE(OUTFILE); 27 CLOSE(INFILE); 28 end COPYOVER; < Ada에서의 다양한 예외들의 사용 예 >
11.4 C++의 예외 처리 C++의 예외 처리기 형식 try 구성 복합문(예외 발생)과 다수의 catch 복합문(예외 처리 루틴)으로 구성 예외 처리 루틴 catch문 함수 형태 형식 매개 변수 오직 한 개(경우에 따라 생략 가능) try { -- 예외가 발생하기를 기대하는 코드 } catch (formal parameter) { -- 예외 처리기 몸체부 . . .
11.4 C++의 예외 처리 사용자 정의 예외만 존재 시스템 예외 처리 불가능 / disable도 불가능 함수에서 발생할 수 있는 예외의 자료형 선언 가능 예) int fun() throw (int, char *) { … } 예외 전파 - 동적 연결 형식매개변수 생략형 예외 처리 catchall - Ada의 others에 해당 명시적 예외 발생 throw 문
#include <iostream.h> void main() { //* 어떤 예외도 발생 가능 int new_grad, index, limit_1, limit_2, freq [10]; short int eof_condition; try { while (1) { If (!cin >> new_grade) //* cin이 eof를 만나면 throw eof_condition; //* eof_condition 예외 발생 index = new_grade /10; { try { if (index < 0 || index > 9) throw (new_grade) ; freq [index]++; } //* 속 try 복합문 끝 catch (int grade) { //* 첨자 오류 처리기 if (grade == 100) freq [9]++; else cout << “ Error -- new grade : “ << grade << “ is out of range “ << end1; } //* catch(int grade) 끝 } //* 속 try 복합문과 catch문 쌍 끝 } //* while 문 끝 } //* 밖 try 복합문 끝 catch (short int) { //* eof 예외 처리기 cout << “ Limits Frequency ” << end1; for ( index = 0 ; index <10 ; index++) { limit_1 = 10 * index; limit_2 = limit_1 + 9; if (index == 9) limit_2 = 100; cout << limit_1 << limit_2 << freq [index] << end1; } //* for 문 끝 } //* catch(short int) 끝 } //* main 끝 { try { if (index < 0 || index > 9) throw (new_grade) ; freq [index]++; } //* 속 try 복합문 끝 catch (int grade) { //* 첨자 오류 처리기 if (grade == 100) freq [9]++; else cout << “ Error -- new grade : “ << grade << “ is out of range “ << end1; } //* catch(int grade) 끝 } //* 속 try 복합문과 catch문 쌍 끝
11.4 Java의 예외 처리 예외의 종류 시스템 정의 예외(System-defined exception or predefined exception) 프로그램의 부당한 실행에 의한 예외 비검사 예외(unchecked exception) Error와 RuntimeException 클래스 ArithmeticException, IOException, IndexOutOfBoundsException, ArrayStoreException, NegativeArraySizeException, NullPointerException, SecurityException, IllegalMonotorException등… 프로그래머 정의 예외(Programmer-defined exception) 프로그래머에 의도적으로 야기되는 예외 검사 예외(checked exception) : 예외 처리기의 존재 검사
< Throwable 클래스의 계층 구조 > 11.4 Java의 예외 처리 < Throwable 클래스의 계층 구조 > RuntimeException Error Exception CheckedException ArithemticException LinkaqeError ThreadDeath VirtualMachineError Object Throwable
11.4 Java의 예외 처리 예외 정의 예외 발생 자바 예외 처리기 C++ 예외 처리기와 동일한 형태 catch문은 매개변수를 갖는다 클래스는 미리 정의한 클래스 Throwable의 후손이어야 함 class MyException extends Exception { public MyException( ) { } public MyException(String message) { super(message); } 예외 정의 MyException myExceptionObject = new MyExeption( ); … throw myExceptionObject; 또는 throw new MyException(“Here is HongKilDong”); 예외 발생
11.4 Java의 예외 처리 예외 처리 바운딩 Java의 throw절 try구문에서 발생한 경우 정적 바인딩 동적 바인딩 catch 함수의 매개변수 발생된 예외 객체나 발생된 예외 객체의 조상 정적 바인딩 내포한 상위 try 구문의 처리기 탐색 동적 바인딩 메소드의 호출자에게 전파 Java의 throw절 C++의 throw절과 유사하지만 의미는 전혀 다르다. Java throw절에 있는 예외 클래스 이름의 의미 그 예외 클래스 또는 후손 예외 클래스가 그 메소드에 의해서 발생될 수 있다는 것을 지정
11.4 Java의 예외 처리 비검사 예외 검사 예외 컴파일러가 전혀 관계하지 않는 예외 클래스 Error와 RuntimeException, 그 후손 클래스들의 예외 검사 예외 메소드에서 발생시킬 수 있는 모든 검사 예외를 throws절에 나열했는지 또는 메소드에 나열했는지를 컴파일러가 확인하는 예외
Import java.io.*; Class NegativeinputException extends Exception { //** 자료 끝을 다루는 예의 정의 public NegativeInputException () { System.out.println(“End of input data reached”); } //** 생성자 끝 } //** NegativeInputException 클래스 끝 Class GradDist { int newGrade, index, limit_1, limit_2; int [] freq = {0,0,0,0,0,0,0,0,0,0}; void buildDist () throws IOException { DataInputStream in = new DataInputStream(System.in); } //** method buildDist 끝 Try { while (true) { systme.out.println(“Please input a grade”); newGrade = Integer.parseInt(in.readLine()); if (newGrade < 0) throw new NegativeInputException(); index = newGrade /10; } //** while(true) ..문 끝 } //** 바깥쪽 try절 끝 Catch (NegativeInputException) { System.out.println (“\nLimits Frequency\n”); for (index=0; index<10;index++) { limit_1 = 10 * index; limit_2 = Limit_1 + 9; if (index ==9) limit_2=100; System.out.println(“ “+limit_1 + “-” + limit_2 + “ “ + freq[index]); } //** for 문 끝 (index = 0;.. } //** catch 문 끝 (NegativeInputException.. try { freq[index]++; } //** 안쪽 try절 끝 catch (ArrayIndexOutOfBoundsException) { if (newGrade ==100) freq[9]++; else System.out.println(“Error – new grade : “ + newGrade + “ is out of range”); } //** catch(ArrayIndex..)절 끝
11.4 Java의 예외 처리 finally 절 프로세스가 반드시 실행되어야 할 상황이 존재하는 경우 폐쇄(close)되어야 할 파일 메소드에 제공된 외부 자원을 해제해야 하는 경우 try { … } catch(…) { …//** More handlers finally { ……
11.4 Java의 예외 처리 C++의 예외처리보다 개선된 점 발생될 수 있는 객체와 프로그램에 있는 모든 다른 객체를 구분 머리부로부터 발생할 수 있지만 처리하지 않은 예외를 알 수 있다. finally절의 추가로 복합문이 종료되는 것에 상관없이 청소작업이 발생하는 것을 허용한다. 사용자 예외 처리기에서 처리될 수 있는 여러가지 시스템 예외를 묵시적으로 발생시킨다.