Media Log


1. 예외 처리(Exception Handling)


예외 처리(Exception Handling)에서 예외(Exception)이란 프로그램 실행 도중에 일어나는 비정상적인 상황을 의미합니다. 이런 상황이 벌어질때, 이를 처리하는 과정을 예외 처리라고 합니다. 예를 들어서, 나눗셈 프로그램에서 사용자로부터 두 개의 정수를 입력받는데, 나누는 수를 0으로 입력한것과 같이 말이죠. 직접 그런 프로그램을 만들어 보도록 합시다.

#include <iostream>

using namespace std;

int main()
{
	int a, b;

	cout << "두 개의 정수를 입력하세요: ";
	cin >> a >> b;
	cout << a << "를 " << b << "로 나눈 몫은 " << a/b << "입니다." << endl;
	return 0;
}

결과:

두 개의 정수를 입력하세요: 10 2

10를 2로 나눈 몫은 5입니다.

..

두 개의 정수를 입력하세요: 5 0

계속하려면 아무 키나 누르십시오 . . .


코드를 보시면, 7행에 입력되는 두개의 정수를 담을 a와 b 변수가 선언되어 있습니다. 그리고 10행에서, 사용자로부터 a, b를 입력받고, 11행에서 a를 b로 나누고 난 뒤의 몫을 출력합니다. 결과를 보시면, 10을 2로 나눈다던가, 5를 3으로 나누면 잘 출력이 되지만, 나누는 수를 0으로 두었더니 프로그램이 갑자기 종료되어 버렸습니다. 기존에는, 이런 상황을 아래와 같이 예외를 처리했습니다.

#include <iostream>

using namespace std;

int main()
{
	int a, b;

	cout << "두 개의 정수를 입력하세요: ";
	cin >> a >> b;
	if (b == 0) // 나누는 수가 0이라면,
		cout << "나누는 수가 0이 될 수 없습니다." << endl;
	else
		cout << a << "를 " << b << "로 나눈 몫은 " << a/b << "입니다." << endl;
	return 0;
}

결과:

두 개의 정수를 입력하세요: 10 2

10를 2로 나눈 몫은 5입니다.

..

두 개의 정수를 입력하세요: 4 0

나누는 수가 0이 될 수 없습니다.

계속하려면 아무 키나 누르십시오 . . .


11행을 보시면, b가 0일 경우에 "나누는 수가 0이 될 수 없습니다."를 출력하고 프로그램이 종료됩니다. 반대로, 0이 아닐 경우에는 몫을 사용자에게 보여줍니다. 나누는 수가 0이 입력되어도, 프로그램은 종료되지 않습니다. 이런 방식으로 예외 처리를 하게 되면, 예외가 발생할때마다 이렇게 처리를 해주어야 하기 때문에 똑같은 코드가 늘어나 코드만 차지하거나, 예외 처리의 구분이 명확하지 않습니다. 그럼 어떻게 하여야만 할까요?


바로, 우리가 지금 배우게될 C++의 예외 처리를 이용하면 쉽게 해결할 수 있습니다.


2. try~catch(시도하다~잡다), throw(던지다)


C++에서 제공하는 예외 처리 메커니즘인 try~catch, throw에 대해 알아봅시다. try~catch, throw의 기본 형식은 아래와 같습니다.

try { // 예외가 발생하는 영역
   if (예외 조건) throw 예외 객체; // 예외가 발생하면 예외를 던지는 영역
} catch (예외 객체) { // 던져진 예외를 잡는 영역
   // 예외 처리 영역
}

살펴보자면, 예외가 발생할만한 영역을 try로 감싸주고, 그 뒤에 try 영역 내에서 예외 조건이 만족하면, throw로 그 예외를 던집니다. 그러면 catch가 그 예외를 잡아 처리해줍니다. 그리고, catch문이 굳이 하나가 아니라 2개 이상 등장해도 됩니다. 던져진 예외 객체와 한번, 위의 나눗셈 예제에서 if문이 아닌 try~catch, throw를 이용한 방법으로 예외 처리를 구현해보도록 하겠습니다.

#include <iostream>

using namespace std;

int main()
{
	int a, b;

	cout << "두 개의 정수를 입력하세요: ";
	cin >> a >> b;

	try {
		if (b == 0) throw b;
		cout << a << "를 " << b << "로 나눈 몫은 " << a/b << "입니다." << endl;
	} catch (int exception) {
		cout << "예외 발생, 나누는 수는 " << b << "가 될 수 없습니다." << endl;
	}
	return 0;
}

결과:

두 개의 정수를 입력하세요: 5 0

예외 발생, 나누는 수는 0가 될 수 없습니다.

계속하려면 아무 키나 누르십시오 . . .


코드를 살펴보시면, 12~17행에서 try~catch 구문이 사용되었습니다. 사용자가 10행에서 a와 b값을 입력하게 하고나서, try 영역 안으로 진입합니다. 13행에서, 만약 b가 0이면(나누는 수가 0이면), 이 b를 throw를 이용해 예외를 던져버립니다. 그럼 이렇게 던져진 예외는, 예외 데이터인 exception에 b의 값이 들어가게 되며, catch가 잡아 처리하게 됩니다.


만약, 예외가 발생하지 않으면 catch 영역은 실행되지 않습니다. 이번엔, 함수 내에서 예외가 발생하였을 경우 그 예외를 처리하도록 해봅시다.


3. 함수 예외 처리(Function Exception Handling)


이름이 func인, 두개의 정수를 인자로 받는 함수를 정의해봅시다. 그리고 그 함수 내에 b가 0이면(나누는 수가 0이면) 예외를 던지도록 하고, 그 아래 몫을 출력하도록 해봅시다. 아래처럼, 함수에서 예외가 발생했을 경우에 어떻게 예외가 처리되는지 살펴보도록 합시다.

#include <iostream>

using namespace std;

void func(int a, int b)
{
	if (b == 0) throw b;
	cout << a << "를 " << b << "로 나눈 몫은 " << a/b << "입니다." << endl;
}

int main()
{
	int a, b;

	cout << "두 개의 정수를 입력하세요: ";
	cin >> a >> b;

	try {
		func(a, b);
	} catch (int exception) {
		cout << "예외 발생, 나누는 수는 " << b << "가 될 수 없습니다." << endl;
	}
	return 0;
}

결과:

두 개의 정수를 입력하세요: 4 0

예외 발생, 나누는 수는 0가 될 수 없습니다.

계속하려면 아무 키나 누르십시오 . . .


코드를 보시면, 5~9행에 func란 함수가 정의되었습니다. 함수 내부를 살펴보시면, 전달받은 b의 값이 0일 경우에 예외를 던지고 있습니다. 그런데, func 함수 내에는 예외를 처리하는 영역이 없기 때문에, func 함수가 호출된 영역으로 예외를 전달합니다.


main 함수 내부로 들어가면, 19행에서 try 내에 func 함수가 호출되었는데, func 함수에서 예외가 발생하면, 예외 데이터를 호출 영역으로 다시 전달합니다. 그럼 다시 전달된 예외 데이터를 catch 영역이 잡아 처리하게 되는 것입니다. (참고로, 기본 데이터형(int, char..)뿐만 아니라 객체(Object)도 예외로 던질 수 있습니다.)


4. 스택 풀기(Stack Unwinding)


위와 같이, 예외를 처리하는 영역이 없어 이 예외가 호출된 영역을 타고 계속 전달되는 현상을 가리켜 스택 풀기(Stack Unwinding)이라고 합니다. 아래 예제를 통해, 스택 풀기가 어떤 것인지 확인해보도록 합시다.

#include <iostream>

using namespace std;

void func1() { throw 0; }
void func2() { func1(); }
void func3() { func2(); }
void func4() { func3(); }

int main()
{
	try {
		func4();
	} catch (int exception) {
		cout << "예외 발생, " << exception << "!" << endl;
	}
	return 0;
}

결과:

예외 발생, 0!

계속하려면 아무 키나 누르십시오 . . .


코드를 보시면, 5~8행에서 func1부터 func4까지 함수가 정의되었습니다. func1에서 예외 데이터를 던지며, func2 함수는 func1 함수 호출을, func3 함수는 func2 함수 호출을, func4 함수는 func3 함수를 호출합니다. main 함수 내의 13행을 보시게 되면, func4 함수가 호출되었습니다. 그러면 아래와 같이, func1 함수까지 호출하겠죠? 함수의 호출 순서는 아래와 같을 것입니다.


func4() -> func3() -> func2() -> func1()


그럼, 예외 데이터는 어떻게 넘어갈까요? 아래를 한번 보도록 합시다.


<스택 메모리(Stack Memory)>


func4() 호출 -> func3() 호출 -> func2() 호출 -> func1() 호출 -> func1 함수 내에서 예외 데이터 던짐 -> func2 함수가 예외 데이터를 받고 다시 func3 함수에 던짐 -> func3 함수가 예외 데이터를 받고 다시 func4 함수로 던짐 -> func4 함수가 예외 데이터를 받고 다시 main 함수 내에 있는 예외 처리 영역으로 던짐 -> 예외 처리


함수가 호출될 때는 저렇게 각 함수의 스택 프레임이 생성됩니다. 그리고, func1 함수에서 throw를 만나고, 자신과 자기를 호출한 함수의 스택을 모두 정리(해제)하고 돌아갑니다. 이것이 스택 풀기(Stack Unwinding)입니다.


이번 강좌는 여기서 마치도록 하겠습니다. 수고하셨고, C++ 강좌는 예외 처리를 마지막으로 끝을 내려 합니다. 나머지 올라오지 않은 강좌는 번외편으로 작성하도록 하겠습니다. 그리고 설명이 부족하다 싶으시면, 덧글로 달아시면 보충 설명을 달아드리도록 하겠습니다.

  1. 이전 댓글 더보기
  2. 지나가다 at 2014.12.14 11:26 신고 [edit/del]

    드래그 안되게 해놓을거면 코드는 왜 적어놓는거지...

    어차피 자바스크립트 끄고 복사해가면 되지만...
    /// 수정본
    저는 장애인입니다 욕먹어도 쌉니다. 저는 바보에요 흐헹헹헤엫에 난 바보다

    Reply
    • 지나가던이 at 2014.12.14 13:36 신고 [edit/del]

      이 정도의 코드도 드래깅하려고 하면 프로그래밍을 왜 하려는지가 더 궁금하네요.

    • BlogIcon EXYNOA at 2014.12.14 17:36 신고 [edit/del]

      복사랑 붙여넣기로 언어를 습득시키고 체화시킬 생각이라면 왜 배우시는건지...

    • 지나가다 at 2014.12.15 01:56 신고 [edit/del]

      그냥 누군가 코드를 복사해서 사용하는 편리함을 누리는것보다 내글을 퍼가지 못하게 하는게 더 중요하다고 하면 되지 뭐 그렇게 합리화를 하는지...

      본인은 수천줄 수만줄에 달하는 라이브러리 코드들도 직접 타이핑해서 습득하고 체화시키면 되겠네요...

      꼭 그렇게 사용하시기 바랍니다.

      http://blog.eairship.kr/243

      이런 코드들은 왜 올려놓은거지

      타이핑 연습하라는건가...

    • BlogIcon EXYNOA at 2014.12.15 13:16 신고 [edit/del]

      스터디의 취지에 벗어난 수단과 방법을 어찌 그렇게 정당화 시키려는지 모르겠습니다. 왜 이렇게 과장해서 자기 주장을 부각하고 상대방의 취지를 깎아내리려고 하시죠?

      오픈소스 라이브러리는 애초에 다른 개발자의 편익을 도모하거나 기존의 프로젝트를 운영하던 도중 그 양이 방대하여 버그를 잡기 어려운 경우, 아니면 다른 개발자의 손의 손을 거쳐 더 나은 프로젝트가 되기를 원해서라던지 공유 라이브러리는 그에 맞는 취지를 가지고 있습니다. 이 강좌 게시글의 취지는 단순한 복사 붙여넣기를 통한 체화, 체득이 아니라 직접 타이핑해보고 그게 점차 손에 베이게 되면 다양한 응용, 심화를 통해서 익혀나가라는 목적으로 본 게시글을 블로그에 게재한 것입니다.

    • BlogIcon EXYNOA at 2014.12.15 13:27 신고 [edit/del]

      너무 확대해서 상반되는 의견을 깎아내리시는 것에만 급급하신 것 같은데 제가 수천, 수만줄의 코드를 강좌 게시글 내에서 쓸 일이 있었으면 복사 붙여넣기를 이미 허용하고도 남았겠죠. 그런 코드를 이미 강좌 게시글에서 썼었다면 그건 스터디 목적을 이미 벗어난게 아닌가요? 그리고 소스 관련 게시판도 그렇고 워게임, 서버/네트워크도 그렇고 다른 게시판도 모두 다 참고 목적으로 사용하라는 겁니다.

    • 루레 at 2014.12.15 13:48 신고 [edit/del]

      크으 강좌글에 드래그는 필수라구욧!!? 머한민국 개발자 썩창 마인드보소 ㅂㄷㅂㄷ 소스짜다 막히면 구글링해서 복붙, 모르겠으면 카페에서 복붙, 그리고 어디가서 나 프로그래머요! 이러니까 머한민국이 개발자 무덤이란 소리를 듣짘ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

    • GLRP at 2014.12.15 18:55 신고 [edit/del]

      실질적으로 처음부터 배울목적으로 강좌 열어본거면
      그대로 직접 타이핑해서 공부하고 타이핑 하던 도중 어떤 구문에서 어떤 역활을 하는지 잘 파악하면 나중에 응용도 더 잘될 뿐더러 프로그래밍이던 뭐던 완성품에서 그 즐거움을 찾는 부분인데 그냥 자기가 좀 안다고 드래그해서 강좌해둔거 사용하면 끝이 아닌데 강좌는..ㅋ
      님만 보라고 올린 강좌는 아닌데
      이렇게 퀄리티 높은 강좌글에 이상한 되도 않는 댓글 쓰면서 눈살 찌푸리게 하는 행동 같네요.

    • 참나 at 2014.12.17 01:29 신고 [edit/del]

      강의 올려주신것만 해도 감사한 일인데
      타이핑치는게 그렇게 귀찮아서 이런 댓글을 다나요??
      돈받고 이렇게 올려주시는것도 아닌데.. 참...
      별에 별 사람도 있네요. 이정도 타이핑도 귀찮아서 복붙하실거면 프로그래머는 천직이 아니신듯 합니다. 게이머나 하심이?

    • 코드몽키 at 2017.12.20 20:03 신고 [edit/del]

      정신나간 인간들 많네.ㅎㅎ

    • 지나가던삼 at 2018.03.28 11:00 신고 [edit/del]

      우선 내용에 충분히 감사하고,

      드래그 안되는 상태에 예제 소스 코드가 길면 조금 불만을 가지겠지만
      코드 길이도 놀면서 쳐도 5분 안에 칠 정도의 양인데 굳이 불만을 토로할 필요가....

  3. 허재영 at 2014.12.17 16:59 신고 [edit/del]

    돈내고 들어도 모자랄만한 강의를 올려주시는 분한테
    감사하다는 말은 못할망정 어찌 저런 댓글을 달 생각을 하시는지 참ㅋ
    마음에 안드는 부분이 있을수도 있으나 최소한의 예의는 갖춰야죠
    누가보면 님한테 돈받고 강의 해주시는 줄 알겠네요 ㅋㅋ

    Reply
  4. kims at 2015.01.14 15:09 신고 [edit/del]

    음.. 뭐 필요하신 분들은 소스보기를 이용하시는 방법이 있습니다..

    Reply
  5. SYP at 2015.02.23 11:30 신고 [edit/del]

    C++ 강좌 끝까지 잘 보았습니다.
    전체적으로 조망해 볼수 있어 좋았고 자신감이 생겨 더 많이 공부하고 싶네요.
    감사합니다. 작성자님~!

    Reply
  6. SYP at 2015.02.23 11:30 신고 [edit/del]

    C++ 강좌 끝까지 잘 보았습니다.
    전체적으로 조망해 볼수 있어 좋았고 자신감이 생겨 더 많이 공부하고 싶네요.
    감사합니다. 작성자님~!

    Reply
  7. jiwu at 2015.03.17 18:04 신고 [edit/del]

    좋은 강좌 감사합니다.

    Reply
  8. lillim at 2015.04.23 18:50 신고 [edit/del]

    수고하셨습니다. 다시 공부하는데 빠르게 도움이 됐습니다.

    Reply
  9. SongHee at 2015.11.09 15:07 신고 [edit/del]

    C++ 강의 ㅋㅋ하루만에 달렸는데
    그럼에도 불구하고 글이 쉽게써져 있어서
    이해도를 높이는데 많은 도움 얻었습니다^^ 감사합니다!

    Reply
  10. cvpr at 2016.01.14 13:31 신고 [edit/del]

    덕분에 c++ remind 공부 제대로 하고 갑니다.. ^^

    Reply
  11. 씨뿔뿔 at 2016.02.12 17:41 신고 [edit/del]

    잘배웠습니다~ 제 주위에도 엑시님처럼 잘하시는 분이 계시면 좋겠네요 ㅠㅠ 후속편은 먼미래에 나오겠죠? 바쁘시다보니..

    Reply
  12. 이희동 at 2016.03.06 20:04 신고 [edit/del]

    올려주신 강좌을 두번이나 열공해서 읽었습니다. 매번 읽을 때마다 보는 관점이 조금 달라지고, c와 c++의 기초적인 개념을 다시 한번 일깨워 주셔서 감사의 글을 남깁니다.

    Reply
  13. ryan c at 2016.05.08 19:51 신고 [edit/del]

    정말 훌륭한 분이라 생각됩니다. 젊은 나이에 실력도 출중하시지만 더욱 놀라운 것은, 그 나이에 걸맞지 않게 매우 성숙하시고 강의를 전달하는 능력이 탁월한 것이 인상적이었습니다. 대단히 감사합니다. 건강하시고 복 많이 받으시고, 외국으로 유학가셔서 훌륭한 소질을 크게 크게 기르셨으면 좋겠어요 :)

    Reply
  14. Tyler at 2016.05.16 02:01 신고 [edit/del]

    덕분에 굉장히 쉽고 빠르게 C++를 공부할 수 있었습니다. 많지 않은 분량인데도 핵심만 잘 짚어주셔서 효율적으로 공부할 수 있었네요. 다른 강의들도 읽어보겠습니다. 감사합니다.

    Reply
  15. 장도익 at 2016.08.08 12:12 신고 [edit/del]

    너무나 알기쉽게 설명해주신덕분에 정말로 많은 도움이 됐습니다.
    이제 갓 입문했는데 하루만에 강좌를 마칠 수 있었습니다.
    감사합니다.

    Reply
  16. Zemma at 2016.11.30 05:32 신고 [edit/del]

    정주행했는데 이렇게 쏙쏙 들어오는 강의는 처음입니다.
    학교수업으로 진행하다 보니 강의가 시원찮고 이해하기 어려워 수업 외적인 부분을 많이 찾아 해맸는데 여기서 끝을 보내요.
    이렇게 좋은 강의 만들어 주셔서 정말정말 감사합니다.

    Reply
  17. 지나가던사람 at 2016.12.08 02:54 신고 [edit/del]

    이렇게 프로그래밍 관련 글을 명확하게 잘 쓰시는 분이 있다니... 구글링 하다가 들어와서 글 몇개 보고있는데 감탄이 나올 따름입니다.

    Reply
  18. jane doe at 2017.01.16 16:18 신고 [edit/del]

    감사합니다. 많이 배웠습니다.

    Reply
  19. 꺼삐딴리 at 2017.08.07 17:15 신고 [edit/del]

    감사합니다. 처음부터 끝까지 잘 보고 갑니다.

    Reply
  20. C++ at 2018.01.02 14:44 신고 [edit/del]

    너무너무 감사합니다. 임베디드 개발자를 목표로
    C는 생각한 기능을 어느정도 자유롭게 표현할 정도로 연습이 되었는데,

    C로만 생각하려고 하다보니 C++은 이해가 참 어려워서 포기했었습니다.

    신입으로 취직후, MFC/QT를 하게되어, 공부를 시작했는데...

    이번에 이 강좌를 보고서 다시! 입문하고 이 강좌를 마치고 나니
    C++에 슬슬 자신감이 생기는군요!

    다른 강좌도 열심히 보고 배워가겠습니다!

    Reply
  21. ㅇㅇ at 2018.06.14 19:23 신고 [edit/del]

    좋은 강좌 감사합니다

    그 어떤 책보다도 명쾌하고 초보자가 궁금해할할 것을 깔끔하게 알려주셨네요

    처음부터 끝까지 쉬지 않고 다 공부하게 되었습니다

    Reply

submit

티스토리 툴바