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을 던지면 안됨.
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<>)를 사용하면 위 문제를 방지할 수 있음.
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>();
를 사용해 해결.