320 likes | 530 Views
프로그래밍 언어론. 10 장 예외 처리. 10.1 설계 주제 10.2 PL/I 의 예외 처리 10.3 Ada 의 예외 처리 10.4 C++ 의 예외 처리 10.5 Java 의 예외 처리 10.6 Pascal 과 C 의 에러 처리. 예외 (exception) 정상적인 처리 상태로부터 벗어나는 이상 (anomaly) 소프트웨어에 의해 탐지되는 비정상적인 조건 뿐만 아니라 하드웨어에 의해 탐지되는 에러들을 포함
E N D
프로그래밍 언어론 10장 예외 처리 10.1 설계 주제 10.2 PL/I의 예외 처리 10.3 Ada의 예외 처리 10.4 C++의 예외 처리 10.5 Java의 예외 처리 10.6 Pascal과 C의 에러 처리
예외(exception) • 정상적인 처리 상태로부터 벗어나는 이상(anomaly) • 소프트웨어에 의해 탐지되는 비정상적인 조건 뿐만 아니라 하드웨어에 의해 탐지되는 에러들을 포함 • 예외가 탐지될 때 예외가 제기(raise)되었다 혹은 신호(signal)가 왔다고 한다. • 예외 처리기(exception handler)는 예외가 탐지되었을 때 실행되도록 설계된 프로시져 또는 일련의 코드로써 예외 처리 후 다시 정상적으로 실행될 수 있도록 하는 것 • 예외 처리는 에러나 인터럽트의 유형에 따라 미리 정해진 곳으로 프로세서의 제어를 자동적으로 옮기는 하드웨어 인터럽트나 에러 트랩과 같은 기능을 프로그래밍 언어에서 구현하려는 시도
10.1 설계 주제(1) • Procedure의 종료 • goto, return (정상) • overflow, underflow, range error - system interrupt • EOF 등의 예외 조건 (예상 가능한 조건) • 해결 방법 • 예외 조건 제어 불가능 언어 • 오류시 약속된 값 반환 –프로그래머가 매번 검사 • 오류 처리 루틴으로 즉시 제어 이동 • 예외 조건 제어 가능 언어 • PL/I : 최초 제공 언어 • MESA, CLU, Ada, C++, Java : 세련된 방법 제공
10.1 설계 주제(2) • 예외 처리 • 프로시져들 사이의 정보 교환 • 정상적인 호출 반환과는 다름 • 프로시져들간의 특별한 제어 허용 • 초기 예외 처리 • 하드웨어 인터럽트 루틴을 사용 • 시스템에서 제공 : 종류, 처리 루틴 • 예외 처리시 고려해야 할 쟁점 • 어떤 프로시져가 발생된 예외를 처리? • 예외 처리 후 예외 발생 프로시저의 활성화 지속 여부?
10.1 설계 주제(3) • 어떤 프로시져가 발생된 예외를 처리? • 활성화된 프로시져 중에서 결정하는 방법 (호출 순서 예: P -> Q -> R) (a) R은 Q에만 신호를 보냄: Q가 R에서 발생된 예외를 처리하는 동안, Q에서 예외가 다시 발생하면 P에 신호를 보낸다. 이 때 P는 이 예외를 처리한 후 Q가 실행하던 작업을 계속할 수 있도록 제어를 넘겨주어 Q가 실행 재개(resume)되고, 결국 R도 실행 재개 (b) R은 Q, P 중 하나를 택해 예외 신호를 보낼 수 있기 때문에 그림과 같은 예외 처리 경우 발생 가능
10.1 설계 주제(4) • 예외 처리의 주요 쟁점 • 인터럽트 기능에 대한 액세스 방법이 제공되었는가? • 사용자가 새로 정의하여 시스템 인터럽트에 우선할 수 있는가? • 사용자 정의 예외가 가능한가? 이 예외를 어떻게 발생시키는가? • 발생 가능한 예외의 영역 규칙은 무엇인가? • 예외 처리기의 영역과 수명 규칙은 무엇인가? • 예외를 발생시킨 프로시져를 실행 재개 혹은 종결시키는가? • 발생된 예외의 전파(propagation)는 어떻게 되는가? • 한 예외에 매개 변수를 사용하여 다양화 시킬 수 있는가? • 예기치 않았던 모든 예외를 처리할 수 있는가? • 예외 처리 루틴에서 예외를 발생 시킬 수 있는가? 이 때 후속 처리는? • 내장된 예외를 위한 디폴트 동작이 존재하거나, 처리기가 제공되어야 하는가? • 내장 예외나 사용자 정의 예외를 무력하게 하는 것이 가능한가?
10.1 설계 주제(5) • 예외 처리기의 영역과 처리기의 결합 procedure X(a,b,c) statement1 with ex_handler1 statement2 begin statement3 statement4 statement5 end with ex_handler2 statement6 end X with ex_handler3 • 만일 예외가 statement3이나 4, 또는 5에서 제기되면, 그것은 ex_handler2의 영역에 있게 된다. statement1에서 제기된 예외는 ex_handler1에 의해 처리된다. statement2나 statement6에서 제기된 예외는 ex_handler3에 의해 처리된다.
10.1 설계 주제(6) • 만일 프로시져 X가 예외 처리기를 가지지 않고 예외가 제기된다고 가정하자. 프로그램은 어디에서 예외 처리기를 찾는가? • 두 가지 명백한 선택이 있다. • X의 영역으로 자신을 포함하는 모든 프로시져에서 예외 처리기를 찾을 때까지 가장 내부의 것을 먼저 살펴본다. 아니면 예외 처리기가 존재하지 않고 프로그램의 실행이 중단된다고 결론을 맺는다. 이것이 정적 영역 해결책이다. • 실행 시간 스택 위의 활동중인 프로시져를 살피고 예외 처리기를 그것들에서 탐색한다. 이것은 동적 영역 해결책이다.
10.2 PL/I의 예외 처리(1) • 시스템 제공 on condition(조건) (예: ON ZERODIVIDE Q := -99;) • 사용자가 직접 예외 발생 (예: IF TEMP < 0.01 THEN SIGNAL ZERODIVIDE;) • 수치계산 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
10.2 PL/I의 예외 처리(2) • 예외 조건 상태 제어 (가능/불능) • enable 선언 : condition 이름 (prefix 사용) • disable 선언 : NO + condition 이름 (prefix 사용) • 예) (NOUNDERFLOW, STRINGRANGE) disable enable • 예외 조건 영역(scope): 접두부에 조건의 이름들을 나열 • 문장 - 한 문장만이 예외 조건 영역 • if문 - condition field만 영역 적용 • procedure, begin -end - 해당 블록 (inner 블록은 상속)
10.2 PL/I의 예외 처리(3) • 예외 처리 루틴 (Exception Handler) • 표준 시스템 예외 처리 루틴 : default –별도 루틴 선언으로 무시 가능 • 예외 처리 루틴 사용자 정의 ON condition-name <on-unit> <on-unit> : 사용자 정의 예외 처리 루틴(문장 또는 블록) • 예외 처리 수행 후 (제어 이동) • 예외를 발생 시킨 문장 • 예외를 발생 시킨 문장 다음 문장 • handler에서 별도로 분기 가능 • 예외 발생 (enable 상태 예외만 가능) • 시스템에서 자동 발생 • 사용자 발생 SIGNAL condition-name SIGNAL condition-name (identifier) : 사용자 정의 예외 취급 가능
10.2 PL/I의 예외 처리(4) 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;
10.2 PL/I의 예외 처리(5) • 특징 • 예외 처리기의 환경 • ON 조건이 부착된 환경 • 매개 변수들이 존재하지 않음 • 예외와 처리기의 바인딩은 동적 • 예외 처리기가 실행된 후에 제기된 예외문으로 제어가 리턴되거나, 종료될 수 있음 • 사용자 정의 예외는 임의의 위치로 분기 가능 • 문제점 • 예외가 일어난 후의 처리가 일관성이 없음 • 프로그래머가 발생한 예외를 무시하고 계속 프로그램을 실행시킬 수 있으므로, 결과적으로 비상식적인 경우 발생 가능 • 예외 처리기의 동적 바인딩은 이해 어려움 • 예외 처리기의 동적 영역 규칙은 예외가 제기된 곳과 문맥상 가까워도 의도하지 않은 채로 예외 처리기가 호출 가능
10.3 Ada의 예외 처리(1) • Steelman Requirements - Ada의 예외 처리에 대한 명세 • 예외 처리 실행 후, 발생 블록 실행 재개 하지 않음 • 다수의 미리 정의된(predefined) 예외 제공 - 시스템 환경 • Ada의 미리 정의된 예외 종류 • CONSTRAINT-ERROR : 영역, 첨자, 열거형 자료 등에 대한 제한 이탈, null 접근시 • NUMERIC-ERROR : 연산 결과가 영역을 벗어날 때 • SELECT-ERROR : select문에서 택일 조건 모두가 만족되지 않을 때 • STORAGE-ERROR : 기억 장소를 할당할 수 없을 때 • TASKING-ERROR : 태스크간에 통신 할 때
10.3 Ada의 예외 처리(2) • Ada의 사용자 정의 예외 • exception 선언문 • 예) BAD_FORMAT, TIMEOUT, XXX : exception • 예외 발생 • 자동 발생 (시스템 정의 예외) • 사용자 발생 (raise문 이용) • 예) raise TIMEOUT
10.3 Ada의 예외 처리(3) • 예외 처리 루틴 • 시스템 제공 예외 처리 • 사용자 예외 처리 루틴 재 정의 가능 (우선) • 사용자 정의 예외 처리 루틴 작성 형태 <exception-handler> ::= when <exception-choice>{|<exception-choice>} => <statements> <exception-choice> ::= <exception-name> | others • 예외 처리 순서 예외 발생 프로그램 예외 처리 루틴 존재 해당 루틴에서 처리 예외 처리 루틴 부재 caller로 예외 전파(dynamic)
10.3 Ada의 예외 처리(4) < Ada 예외 처리 루틴 구문 예 > begin -- this is a sequence of statements exception when NUMERIC_ERROR => -- 수치 오류를 처리하는 작업 when BAD_FORMAT => -- 어떤 예외 처리 작업 whenothers => -- 위 두 예외를 제외한 모든 예외를 end; 처리하는 작업
10.3 Ada의 예외 처리(5) < Ada 예외 처리 예 > 1 procedure P is 2 BAD-FORMAT:exception; 3 procedure Q is 4 begin 5 . . . 6 if S /='' thenraise 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;
예외사항 발생 10.3 Ada의 예외 처리(6) • 예외 사항의 전파 • 예외 사항이 발생되었지만 해당 예외 처리기가 없는 경우는 호출한 상위 프로그램으로 제어가 넘어감 예외의 전파 (Propagation of Exception)
10.3 Ada의 예외 처리(7) procedure DOSOMETHING is HANDLE_ERROR:exception; begin -- perform some set of actions exception when HANDLE_ERROR => -- error handing code end; end DOSOMETHING; function SECURE_DIVIDE(X , Y:REAL) return REAL is begin return X / Y; exception when NUMERIC_ERROR => return 0; end SECURE_DIVIDE; procedure COPYOVER is begin OPEN(INFILE); OPEN(OUTFILE); loop GET(INFILE , CHARACTER); PUT(OUTFILE , CHARACTER); end loop; exception when END_OF_FILE => PUT(OUTFILE , EOF); CLOSE(OUTFILE); CLOSE(INFILE); end COPYOVER; < Ada에서 다양한 예외들의 사용 예 >
10.3 Ada의 예외 처리(9) • 예외 발생 억제 • pragma SUPPRESS(OVERFLOW_CHECK) • 이 pragma의 영역에서는 오버플로우 검사 필요 없음 • 문제점 • 예외가 발생할 때 예외 처리 루틴에 매개변수를 전달할 수 없다. 따라서 프로그래머는 전역 변수를 통해서만 통신할 수밖에 없는데, 이것은 모듈화에 위배된다. • 발생된 예외가 예외 처리 루틴을 찾기 위해 동적 체인의 마지막까지 전파된다. 만일 프로그래머가 적절한 위치에 예외 처리 루틴을 기술하지 못하면, 예상하지 못한 곳에서 예외가 처리되어 결국 디버깅이 어렵게 된다.
10.4 C++의 예외 처리(1) • C++의 예외 처리기 형식 • try 문(예외 발생)과 다수의 catch 문(예외 처리 루틴)으로 구성 • 예외 발생을 알려주는 객체를 throw 명령으로 예외 처리기에 보냄 • 예외 처리 루틴 catch문 • 함수 형태 • 형식 매개변수 오직 한 개(경우에 따라 생략 가능) try { -- 예외가 발생하는 것을 예상하는 코드 } catch (formal parameter) { -- 예외 처리기 몸체부 } . . . catch (formal parameter) { -- 예외 처리기 몸체부 }
10.4 C++의 예외 처리(2) • 사용자 정의 예외만 존재 • 시스템 예외 처리 불가능 • 함수에서 발생할 수 있는 예외의 데이터 형(throw에서 사용될 식의 데이터 형) 선언 가능 • 예) 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 끝 10.4 C++의 예외 처리(3) < C++의 예외 처리기 사용 예 >
10.5 Java의 예외 처리(1) • 예외 처리의 장점 • 정상적인 코드와 에러처리 코드의 분리 • 호출 스택을 이용하여 에러를 전달 • 에러의 종류와 차이를 이용하여 그룹화 가능 • 예외의 종류 • 시스템 정의 예외(System-defined exception or predefined exception) • 프로그램의 부적당한 실행에 의한 예외 • 비검사 예외(unchecked exception) • Error와 RuntimeException 클래스: … • 프로그래머 정의 예외(Programmer-defined exception) • 프로그래머에 의도적으로 야기되는 예외 • 검사 예외(checked exception) : 예외 처리기의 존재 여부 검사
Object Throwable LinkaqeError ThreadDeath Error Exception VirtualMachineError RuntimeException CheckedException ArithemticException 10.5 Java의 예외 처리(2) < Throwable 클래스의 계층 구조 >
10.5 Java의 예외 처리(3) • 자바 예외 처리기 • 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”); 예외 발생
10.5 Java의 예외 처리(4) • 예외 처리 바인딩 • try 문에서 발생한 경우 • catch 함수의 매개변수 • 발생된 예외 객체나 발생된 예외 객체의 조상 • 정적 바인딩 • 내포한 상위 try 구문의 처리기 탐색 • 동적 바인딩 • 메소드의 호출자에게 전파 • Java의 throw절 • C++의 throw절과 유사하지만 의미는 전혀 다름 • Java throw절에 있는 예외 클래스 이름의 의미 • 그 예외 클래스 또는 자손 예외 클래스가 그 메소드에 의해서 발생될 수 있다는 것을 지정
10.5 Java의 예외 처리(5) • 비검사 예외 • 컴파일러가 전혀 관계하지 않는 예외 • 클래스 Error와 RuntimeException, 그 자손 클래스들의 예외 • 검사 예외 • 메소드에서 발생시킬 수 있는 모든 검사 예외를 throws절에 나열했는지 또는 메소드에서 처리할 수 있는지를 컴파일러가 확인하는 예외
10.5 Java의 예외 처리(7) • finally 절 • 프로세스가 반드시 실행되어야 할 상황 정의 • 파일 close • 메소드에 제공된 외부 자원을 해제 try { … } catch(…) { … } …// More handlers finally { …… }
10.5 Java의 예외 처리(8) • 전달해야 하는 예외의 종류를 선택하는 방법 • 이미 만들어진 예외 클래스를 사용 • 사용자가 필요한 예외 클래스를 새로이 작성 • C++의 예외 처리보다 개선된 점 • 예외가 발생될 수 있는 객체와 프로그램에 있는 모든 다른 객체를 구분 • finally절의 추가로 문장이 종료되는 것에 상관없이 정리 작업이 발생하는 것을 허용 • 사용자 예외 처리기에서 처리될 수 있는 여러 가지 시스템 예외를 묵시적으로 발생