예외처리

 

예외란?
할당되지 않은 메모리에 접근하거나, 할당 할 수 없는 너무 큰 메모리를 할당하는 등의
문법상에는 문제 없지만 실행해보면 오류가 발생하는 정상적이지 않은 상황들

C에서의 예외 처리방식

1
2
3
4
5
6
char *= (char*)malloc(1000000000);
if(c == NULL)
{
printf("메모리 할당 오류");
return;
}
 
 

위처럼 일단 해보고, 잘 됐는지 값을 확인해보고, 잘 됐으면 동작하게, 잘 안됐으면 특정 값을 리턴하게 했었음

C++에서는 특정 값을 리턴할 필요 없이 throw를 사용해서 명시적으로 나타 낼 수 있음

throw std::out_of_range("vector 의 index 가 범위를 초과하였습니다.");

위처럼 throw로 out_of_range 객체를 던져주면 됨.

C++ 표준 라이브러리에는 out_of_range 외에도 overflow_error, length_error, runtinm_error 등등 여러 예외 객체가 정의되어 있음
꼭 정의되어있는 객체를 던지지는 않아도 됨, 스스로 만든 객체를 던질 수도 있음

각 객체가 어떤 기능을 가지고 있다기보다는 일종의 예약어 느낌인듯 함
예를들어 3칸짜리 벡터에서 4번째 칸에 접근하는 경우

 
if(index>vec.size()) throw out_of_range("예외 발생");
 

처럼 쓰는 방식이고, 결국 범위밖인지 판단하는건 if 내부에서 직접 하고 던지는 객체명만 out_of_range인것
if(out_of_range) 처럼 쓰는게 아님

throw하면 해당 위치에서 즉시 함수가 종료되고 뒷부분은 실행되지 않고, 예외 처리하는 부분으로 바로 감
또한 함수에서 할당한 stack에 있는 객체나 값들을 모두 소멸시켜줌

함수 호출하는쪽에서 예외가 발생 할 수도 있겠다 싶으면 try로 감싸줌
호출된 함수쪽에서 예외가 발생하면 throw 해주고
호출하는 쪽에서 catch문으로 받아줌

생성자에서 예외를 던질땐 소멸자가 호출되지 않음. 
객체가 끝까지 생성되지 않았으니 생성된게 없다고 판단하고 소멸자가 호출되지 않음
그러니 이런 경우 catch문에서 잘 해제시켜 줘야함

catch문은 여러개 쓸 수 있음

1
2
3
4
5
6
7
8
9
10
11
  try {
    func(c);
  } catch (char x) {
    std::cout << "Char : " << x << std::endl;
  } catch (int x) {
    std::cout << "Int : " << x << std::endl;
  } catch (std::string& s) {
    std::cout << "String : " << s << std::endl;
  } catch (const char* s) {
    std::cout << "String Literal : " << s << std::endl;
  }

위처럼 쓰면 발생한 예외가 위에서부터 들어갈 수 있는곳에 들어가서 해당 catch문으로 처리함

 

만약 
catch(부모클래스 x) {}
catch(자식클래스 x) {}
처럼 catch문이 있으면 부모객체던 자식객체던 다 부모클래스쪽에 들어갈 수 있으니 위에서 다 걸림
그러니 자식클래스는 자식클래스 방식으로 처리하고 싶다면 
catch(자식클래스 x) {}
catch(부모클래스 x) {}
처럼 자식클래스가 위로 가게 해서 자식클래스는 들어가고, 부모클래스는 아래로 들어가게 순서를 바꿔줘야 함