안녕하세요. 명월입니다.
이 글은 C++에서 예외처리(try ~ catch, throw) 사용법에 대한 글입니다.
C++에서의 예외 처리는 엄청 단순합니다. 오히려 Java와 C#등의 다른 언어 때문에 헤갈립니다.
일단 C#의 예외처리와 비교를 하겠습니다. (다른 언어도 비슷합니다.)
링크 - [C# 강좌 - 21] 예외 처리
먼저 C#과 가장 다른 특징은 c++은 finally가 없습니다. try ~ catch만 있습니다. 그렇기 때문에 finally로 메모리나 리소스 반환이 안됩니다.
#include <stdio.h>
#include <iostream>
using namespace std;
// Node 클래스
class Node
{
// 접근 제한자 설정 - 내부 참조 전용
private:
// data 값 선언
const char* data = "hello world";
public:
// 값 취득
const char* getData()
{
return data;
}
};
// Node의 값을 취득하는 함수
const char* getData()
{
// try ~ finally의 구문은 c++에서 존재하지 않는다.
try
{
// Node 클래스의 메모리 할당
Node* node = new Node();
// data값 취득 리턴
return node->getData();
}
finally
{
// return하고 나서 메모리 해제
delete node;
}
}
// 실행 함수
int main()
{
// 메모리 취득
const char* data = getData();
// 콘솔 출력
cout << data << endl;
return 0;
}
node에서 값을 할당하고 finally에서 메모리 해제를 하고 싶은데 finally가 없다고 에러가 나옵니다.
그래서 조금 소스를 귀찮게 해제하고 리턴하는 방식으로 작성해야 합니다.
위처럼 작성 해야 합니다. 사실 C/C++에서 finally가 없었는데 Java, C#에서 생긴 것이겠습니다. 저도 C/C++를 오랫만에 정리하다보니 글을 쓰면서 알았네요.. C/C++은 finally가 없었습니다...
C/C++할 때는 몰랐다가 Java와 C#을 주로 사용하는 현재는 finally가 없으니깐 불편하기도 하고 엄청 이상하네요...
두번째는 throw가 되지 않는 예외 처리는 잡을 수 없습니다. 즉, Java나 C#은 에러가 발생하면 무조록 try ~ catch로 날라갑니다만, c++는 null이라고 해도 throw를 던지지 않으면 그냥 runtime에러가 발생합니다.
#include <stdio.h>
#include <iostream>
using namespace std;
// Node 클래스
class Node
{
// 접근 제한자 설정 - 내부 참조 전용
private:
// data 값 선언
const char* data = "hello world";
public:
// 출력 함수
void print()
{
// 콘솔 출력
cout << data << endl;
}
};
// 실행 함수
int main()
{
try
{
// Node 클래스의 메모리 할당
Node* node = new Node();
// 메모리 삭제
delete node;
// print()함수 호출.. 그러나 메모리가 삭제되었기 때문에.. data값에서 에러가 발생..
node->print();
}
catch (...)
{
// 에러가 발생하면 catch함
cout << "catch" << endl;
}
return 0;
}
여기까지 보면 Java나 C#을 생각하면 null 에러가 발생해서 catch에 잡힐 것 같습니다.
분명 에러가 발생했는데 try ~ catch에 잡히지 않습니다. 이게 다른 것입니다.
#include <stdio.h>
#include <iostream>
using namespace std;
// Node 클래스
class Node
{
// 접근 제한자 설정 - 내부 참조 전용
private:
// data 값 선언
const char* data = "hello world";
public:
// 출력 함수
void print()
{
// 에러 발생.
throw 100;
// 콘솔 출력
cout << data << endl;
}
};
// 실행 함수
int main()
{
// Node 변수 선언
Node* node;
try
{
// Node 클래스의 메모리 할당
node = new Node();
// print()함수 호출
node->print();
}
// throw가 int형일 경우.
catch (int e)
{
// 에러가 발생하면 catch
// 콘솔 출력
cout << "error code " << e << endl;
}
// 메모리 삭제
delete node;
return 0;
}
이번에는 print함수 안에서 throw int을 날렸습니다. catch(int)로 그 throw를 받았습니다.
if else와 try ~ catch는 비슷한 형태를 가집니다. 구조적으로 보면 try ~ catch가 더 좋아보입니다. 호출되는 하위 함수에서도 throw만 날리면 catch가 있는 곳으로 포인터가 이동하니깐 말입니다.
그러나 try ~ catch는 if else와 다르게 throw를 날리면 overhead가 발생하기 때문에 성능에 저하가 발생합니다. 그래서 최대한 if else로 걸러주는게 중요합니다. 그러나 문제는 if else로만 작성을 한다면 로직은 엄청 지저분해지고 복잡해 질 것입니다.
사양에 따라 if else 분기가 자주 발생하고 if 대비 else가 50:50이라면 당연히 if else를 써야 하지만, 분기의 대비가 99 : 1 이라면, 즉, 대부분 if안의 처리가 실행되고 간혹 else 문이 발생한다고 한다면 try catch throw도 고려해 볼 만한 사항입니다.
여기까지 C++에서 예외처리(try ~ catch, throw) 사용법에 대한 글이었습니다.
궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.
'Study > C , C++ , MFC' 카테고리의 다른 글
[C++] map(맵)의 사용법 (0) | 2020.04.09 |
---|---|
[C++] vector(리스트)의 사용법 (Stack, Queue 알고리즘 예제) (0) | 2020.04.08 |
[C++] 쓰레드(Thread)를 사용하는 방법 (0) | 2020.04.07 |
[C++] IO (fstream)(파일 읽기 쓰기)를 사용하는 방법 (0) | 2020.04.06 |
[C++] 리터럴 문자열(const char*, const wchar_t*)과 typedef, operator의 사용법 (0) | 2020.04.02 |
[C++] 람다식(functional) 사용법과 클로저(closure) 그리고 auto 자료형 (0) | 2020.03.22 |
[C++] namespace와 using 사용법 (1) | 2020.03.20 |
[C++] 접근 제한자, 추상 클래스(순수 가상 메서드), 오버로드(Overloading)와 오버라이딩(Overriding) (0) | 2020.03.20 |