[C++] exception

haeryong·2023년 1월 28일
0

Exception

  • try 내의 코드를 실행하는 도중 throw가 발생하면 catch 구문에서 해당 throw를 catch함.
  • 이때 throw는 객체 R-value이며 catch는 throw한 객체의 reference로 받아야 함.
  • 예시에서는 exception을 include하고 exception 객체를 throw하고 catch했지만 원하는 객체를 throw, catch할 수도 있음.
  • catch(...) 구문을 통해 어떤 객체가 throw되더라도 catch할 수도 있다.
#include <exception>

int divide(int a, int b)
{
    if (b == 0)
    {
        throw std::runtime_error("divide by 0");
    }
    return a / b;
}

int main()
{
    try
    {
        f();
    }
    catch (const std::exception &e)
    {
        std::cerr << e.what() << std::endl;
    }
}

  • exception을 사용한 경우에 throw가 던져지는 경우 overhead가 발생한다. for loop와 같이 반복적으로 불러지는 경우에는 exception을 사용하지 않는 게 좋을수도 있다. profile을 찍어보고 판단하는 것이 바람직함.

  • 함수 내에서 error handling이 가능한 경우 exception을 사용할 필요 없다.

  • c++의 constructor는 return이 없기 때문에 exception을 사용하면 좋음.

  • destructor, swap, move, default construct는 exception을 던지면 안됨.

Stack unwinding

  • throw 발생 시 try, catch 구문이 있는 함수까지 stack frame을 pop함.

  • main 함수에도 try, catch 구문이 없는 경우 std::terminate() 함수가 콜이 되면서 process가 종료됨.

  • memory leak이 생기는 것을 주의해야한다. throw가 던져진 경우 try catch 구문을 만날 때까지 stack unwinding하기 때문.(메모리를 free하지 못하고 함수를 종료함.)
    -> RAII idiom를 충족시키도록 smart pointer(unique_ptr<>)를 사용하면 위 문제를 방지할 수 있음.

Exception safety

0. No Exception safety


int divide(int a, int b)
{
	if(b == 0)
    {
    	throw std::runtime_error("divide by 0");
    }
    return a/b;
}

void f()
{
	Ojb* obj = new Obj();
    divide(10, 0);
    delete obj;
}

int main()
{
	try
    {
    	f()
    }
    catch(const std::exception& e)
    {
    	std::cout << e.what() << std::endl;
    }
    
}

delete ojb가 실행되지 않고 종료돼 memory leak 발생.
unique_ptr<Obj> obj = std::make_unique<Obj>();를 사용해 해결.

1. Basic Exception safety

  • Resource leak 없음.
  • exception이 던져지면 프로그램의 state가 변할 수 있음.

2. Strong Exception safety

  • exception이 던져져도 프로그램의 state가 변하지 않음.
  • exception이 던져질 수 있는 함수는 모두 프로그램의 상태를 변경시키는 코드보다 앞쪽에 배치하고, exception이 던져질 수 있는 함수의 return이 필요한 경우 모두 로컬 변수로 저장.

3. No-throw guarantee

  • exception이 던져지지 않는 함수.
  • 상위 함수까지 exception이 propagation되지 않도록 exception handling을 마무리함.

0개의 댓글