C++: try throw/catch

C++의 C에 대한 장점 중 하나가 exceptional case에 대한 대응 방법이 아닐까 한다. 즉, C에서 예외적인 경우가 발생하면 프로그램이 그냥 죽든가 오작동을 하게 되는데, C++에서는 이것에 대해서 별도의 대처가 가능하다는 이야기이다.

이것을 가능하게 해주는 것이 try/throw/catch이다. 물론 C++ 말고도 다른 객체지향적 언어가 이것을 지원한다.

try는 말 그대로 중괄호 안에 있는 내용을 한번 해보는 것이다. 문제가 생기면 (예외 상황이 생기면) catch로 연결된다.

throw는 catch를 부르는 것이다. 즉, 예외가 발생했음을 알린다.

catch는 예외상황의 handler이다. 예외 상황이 생겼을 때 대처하는 코드가 들어가게 된다.

쉬운 예를 들면

#include <iostream>
using namespace std;

double division(int a, int b) {
    if( b == 0 ) {
        throw "Division by zero condition!";
    }
    return (a/b);
}

int main () {
    int x = 50;
    int y = 1;
    double z = 0;
    
    try {
        z = division(x, y);
        cout << z << endl;
    }catch (const char* msg) {
        cerr << msg << endl;
    }
    
    return 0;
}

쉬운 예이지만 필요한 내용은 모두 담고 있다. 0으로 나눴을 때 일반적으로 프로그램은 비정상적으로 crash한다. 반면 이 프로그램은 적절한 대처 (왜 문제가 생겼는지)를 하고 정상적으로 프로그램을 종료하게 된다.

읽어보면 division 함수를 부르는 일을 일단 try한다. division 함수에서는 0으로 나눌 때 throw를 한다. throw를 하면 이 때 catch에서 받게 된다.

즉, 나누는 일을 일단 try해보고 별 일 없으면 실행이 종료되지만, 0으로 나누게 되면 throw에서 0으로 나눴다는 메시지를 던지게 되고, 그 다음 catch에서 그 메시지를 받아서 메시지를 내보내는 일을 수행하고 프로그램이 종료하게 된다.

이 과정을 모두 생략하면 0으로 나눴을 땐 0으로 나눴다며 fatal error를 내며 프로그램이 비정상 종료되는 반면, 이렇게 하면 error message를 내보내고 정상적(?)으로 종료하게 된다.

exceptional case를 다루는 이유는 그 때문이다. 비정상적인 종료를 막기 위함이다. 프로그램을 작성하면서 불안정한 부분은 존재하게 마련이다. 작성하는 동안에도 알 수 있다. 이 부분이 나중에 문제를 일으킬지 아닐지 말이다.

아주 흔하게 메모리를 할당하는 부분이라든가 할당한 메모리에 접근하는 과정에서 예상치 않은 예외상황이 발생할 수 있다. 이런 흔한 예외상황에 대해서는 C++ standard library에서 별도로 정의를 하고 있을 정도로 잘 대처하고 있다. 만일 이런 문제가 생길 때마다 덩치가 큰 프로그램을 또는 벌려놓은 일이라든가 작업중인 파일을 제대로 닫지 못하고 비정상적으로 종료하는 것 보다는 예외 상황이 어떤 것인지 알리고 진행하던 작업 혹은 파일들을 최대한 잘 보전해놓고 종료하는 것이 좋다.

그런 의미에서 이 코드를 사용한다. 그러나 try/throw/catch를 친절하게 잘 다뤄놓은 소프트는 많이 보지 못했다. 다들 촉박하게 개발을 했는지 아예 이러한 exception에 대한 handling을 해본 적이 없든지 해서일 것이다.

솔직히 exceptional case에 대한 대처가 잘 되어있는 software와 그렇지 않은 software의 차이는 exceptional case가 빈번히 일어나야 알 수 있기 때문에 exceptional case의 발생을 전혀 인정하지 않는다거나 있을 수 없다 생각하면 이런 배려를 해둘 이유도 없을 수 있다.

대처를 해놓든 안 해놓든, 프로그램에서 정해놓은 일을 정상적으로 수행하지 못했다면 다음 작업으로 진행할 수가 없는 경우가 많아서 어떻게든 ‘망’한 것이니까 crash해서 망하든 친절하게 상황을 정리해주고 망하든 망한 것이다.

요약해보자면,