C++/Exception 2021. 3. 22. 00:10

스택 되감기 (Stack Unwinding)

  • throw를 통해 던질 경우, 타입에 맞는 catch를 만날 때까지 스택을 되감는다.

    • throw 뒤의 코드는 실행하지 않는다.

    • 마찬가지로 catch를 만나지 못해서 스택을 되감는 경우에도 뒤의 코드를 실행하지 않고 바로 리턴한다.

    • 아래 코드를 디버깅하여 한 줄씩 보면 이해하기 편하다.

    #include <iostream>
    
    using namespace std;
    
    void        last()
    {
      cout << "Last function\n";
      cout << "Throw exception\n";
    
      throw - 1;
    
      cout << "End Last\n";
    }
    
    void        third()
    {
      cout << "Third function\n";
    
      last();
    
      cout << "End Third\n";
    }
    
    void        second()
    {
      cout << "Second function\n";
    
      try
      {
        third();
      }
      catch (double)
      {
        cerr << "Second caught int exception\n";
      }
    
      cout << "End Second\n";
    }
    
    void        first()
    {
      cout << "First function\n";
    
      try
      {
        second();
      }
      catch (int)
      {
        cerr << "First caught int exception\n";
      }
    
      cout << "End First\n";
    }
    
    int            main()
    {
      cout << "Main Start\n";
    
      try
      {
        first();
      }
      catch (int)
      {
        cerr << "Main caught int exception\n";
      }
    
      cout << "End Main\n";
    }
    
    /* stdout stderr
    Main Start
    First function
    Second function
    Third function
    Last function
    Throw exception
    First caught int exception
    End First
    End Main
    */

Ellipses

  • 생략 부호(...)를 사용하여 명시하지 않은 예외들에 대한 처리를 할 수 있다.

    #include <iostream>
    
    using namespace std;
    
    void        last()
    {
      cout << "Last function\n";
      cout << "Throw exception\n";
    
      throw 'a';
    
      cout << "End Last\n";
    }
    
    void        third()
    {
      cout << "Third function\n";
    
      last();
    
      cout << "End Third\n";
    }
    
    void        second()
    {
      cout << "Second function\n";
    
      try
      {
        third();
      }
      catch (double)
      {
        cerr << "Second caught int exception\n";
      }
    
      cout << "End Second\n";
    }
    
    void        first()
    {
      cout << "First function\n";
    
      try
      {
        second();
      }
      catch (int)
      {
        cerr << "First caught int exception\n";
      }
    
      cout << "End First\n";
    }
    
    int            main()
    {
      cout << "Main Start\n";
    
      try
      {
        first();
      }
      catch (int)
      {
        cerr << "Main caught int exception\n";
      }
      catch (...)
      {
        cerr << "Main caught ellipses exception\n";
      }
    
      cout << "End Main\n";
    }
    
    /* stdout stderr
    Main Start
    First function
    Second function
    Third function
    Last function
    Throw exception
    Main caught ellipses exception
    End Main
    */

Exceiption Specifier

  • 함수를 정의할 때 body 전에 throw(자료형)의 형식으로 작성하여 예외를 던질 가능성이 있는 함수임을 명시할 수 있다.

    void        last() throw(...)
    {
      cout << "Last function\n";
      cout << "Throw exception\n";
    
      throw 'a';
    
      cout << "End Last\n";
    }
  • throw() 처럼 파라미터를 작성하지 않을 경우에는 "예외를 던지지 않는다" 라는 뜻으로 사용된다.

    void        last() throw()
    {
      cout << "Last function\n";
      cout << "Throw exception\n";
    
      throw 'a';
    
      cout << "End Last\n";
    }
    warning C4297: 'last': function assumed not to throw an exception but does