본문 바로가기
CPP

CPP Exception - 2

by yongckim 2021. 11. 28.
728x90
반응형
다른 함수를 호출했을 때 예외처리

다음과 같이 try문 안에서 함수를 호출한 후 해당 함수에서 try, catch를 사용하지 않고 throw를 보내면 어떻게 될까요?

 

catch문이 존재하지 않아 에러가 발생하게 될까요?

 

다음과 같이 함수를 작성해보고 실행해봅시다.

 

#include <iostream>

using namespace std;

void func() {
	throw 1;
}

int main() {
	try {
		func();
	}
	catch(...) {
		cout << "Exception occurred!" << endl;
	}
}

위과 같이 메인문의 catch 문에게 throw가 전달된 것을 볼 수 있습니다.

 

함수에서 throw가 발생했는데 catch 구문이 없을 경우 호출한 함수로 전달됩니다.

 

스택 되감기(Stack Unwinding)

위와 같이, 예외를 처리하는 영역이 없어서 throw로 보낸 예외가 호출된 영역으로 계속해서 전달되는 현상을 가리켜 스택 되감기(Stack Unwinding) 이라고 합니다.

 

#include <iostream>
#include <string>
using namespace std;

void func1() {
	throw 1;
}

void func2() {
	try {
		func1();
	}
	catch(double n) {
		cout << "func2 Exception" << endl;
	}
}
void func3() {
	try {
		func2();
	}
	catch(int n) {
		cout << "func3 Exception" << endl;
	}
}

int main() {
	try {
		func3();
	}
	catch(...) {
		cout << "main Exception" << endl;
	}
}

위의 코드에서 다음과 같은 흐름으로 진행됩니다.

  1. 메인 함수에서 func3이 호출됩니다.
  2. func3에서 func2가 호출됩니다.
  3. func2에서 func1이 호출됩니다.
  4. func1에서 예외를 발생시킵니다.
  5. func1에 예외를 catch하는 구문이 없기 때문에 이전에 호출한 func2로 예외를 넘깁니다.
  6. func2의 catch와 예외가 다른 자료형이기 때문에 이전에 호출한 func3으로 예외를 넘깁니다.
  7. func3의 catch와 예외의 자료형이 같으므로 func3의 catch를 실행시킵니다.
  8. 발생한 예외가 func3에서 처리되었으므로 main은 예외처리가 발생하지 않습니다.
예외 지정 (C++ 98)

함수를 정의할때 함수내에 발생 가능한 예외의 종류를 명시할 수 있습니다.

 

함수에 예외 지정에 지정한 것 이외의 형태를 다른 함수에게 전달하게 될 경우 std::unexpected가 호출됩니다.

 

#include <iostream>
#include <string>
using namespace std;

void func1() throw(int) {
	throw 1.0;
}

void func2() {
	try {
		func1();
	}
	catch(double n) {
		cout << "func2 Exception" << endl;
	}
}
void func3() {
	try {
		func2();
	}
	catch(int n) {
		cout << "func3 Exception" << endl;
	}
}

int main() {
	try {
		func3();
	}
	catch(...) {
		cout << "main Exception" << endl;
	}
}

다음과 같이 에러가 발생하는 것을 볼 수 있습니다.

 

하지만 예외 지정은 함수에서 던진 예외를 지정하는 기능으로 함수의 외부에 예외를 보내지 않으면 문제가 되지 않습니다.

#include <iostream>
#include <string>
using namespace std;

void func1() throw(int) {
	try {
		throw 1.0;
	}
	catch (...) {
		cout << "func1 Exception" << endl;
	}
}

void func2() {
	try {
		func1();
	}
	catch(double n) {
		cout << "func2 Exception" << endl;
	}
}
void func3() {
	try {
		func2();
	}
	catch(int n) {
		cout << "func3 Exception" << endl;
	}
}

int main() {
	try {
		func3();
	}
	catch(...) {
		cout << "main Exception" << endl;
	}
}

만약 throw()와 같이 괄호안에 아무것도 넣지 않는다면 예외가 발생하지 않는 함수라는 것을 명시하는 것입니다.

 

외부로 예외를 보내려고 할 시 에러가 발생하게 됩니다.

 

#include <iostream>

using namespace std;

void func() throw(){
	throw 1;
}

int main() {
	try {
		func();
	}
	catch(...) {
		cout << "main Exception" << endl;
	}
}

컴파일 할때도 경고가 발생하는 것을 볼 수 있습니다.

 

물론 함수 외부로 예외를 보내지 않으면 함수 이름 뒤에 throw()를 명시해도 에러가 발생하지 않습니다.

 

#include <iostream>

using namespace std;

void func() throw(){
	try {
		throw 1;
	}
	catch(...) {
		cout << "func Exception" << endl;
	}
}

int main() {
	try {
		func();
	}
	catch(...) {
		cout << "main Exception" << endl;
	}
}

반응형

'CPP' 카테고리의 다른 글

CPP Standard Template Library - iterator  (0) 2021.12.11
CPP Template  (0) 2021.12.09
CPP Casts  (0) 2021.12.04
CPP Exception - 3  (0) 2021.11.28
CPP Exception - 1  (0) 2021.11.27