Home > Articles > Programming > C/C++

C++ Reference Guide

Hosted by

Function Try Blocks FAQ

Last updated Jan 1, 2003.

After reading the overview of function try blocks I received questions about the usefulness of the said feature. Some readers ask whether they can use function try blocks to catch construction exceptions of namespace-scope objects by placing a function try block after main(). Others ask about the use of function try blocks in destructors and regular functions. Find out all the answers here.

Question: I have a global object that might throw during construction. Can I use a function try block on main() to catch such an exception?

Answer: Namespace scope objects (a category that includes global objects) are conceptually constructed before main() starts. Let's look at an example:

C obj; //global object that might throw during construction
main()
try //is it allowed?
{
}
catch(exception &e)
{
  // doesn't catch exceptions from obj's ctor or dtor
}

If an exception is thrown during the construction of obj, there is no way to handle that exception. Placing a function try block right after main() will not do. The C++ standard explicitly prohibits that. Even if it were allowed, the handler would have to re-throw the exception anyway.

For similar reasons, you cannot catch exceptions thrown from the destructor of obj using a function try block.

Question: Can I use a function try block to catch exceptions thrown from a destructor?

Answer: Generally speaking, destructors should not throw exceptions at all. Yet technically, a function try block can be used on destructors:

C::~C() try { } catch(exception &e) { // must re-throw }

However, there is no way to get out of a destructor's function try block handler except by throwing a new exception or re-throwing the original exception that's been caught. Therefore, using function try blocks on destructors is less useful than it might seem.

Question: My constructor doesn't have a member initialization list but it might throw. Can I use a function try block in this case?

Answer: In the absence of member initializers, there's no reason for using a function try block. Consider:

C::C()
try //function try block
{
  p = new char[TERABYTE];
 }
 catch(bad_alloc& )
 {
  cerr<<"allocation failure!";
 //rethrow 
}

Instead, you can handle any potential exceptions by using traditional exception handling inside the constructor body:

C::C()
{ 
 try //traditional exception handling
 {
  p = new char[TERABYTE];
 }
 catch(bad_alloc& )
 {
  cerr<<"allocation failure!";
 }
}

As an aside, if your constructor might throw you may want to reconsider a different design approach such as the two-phased construction idiom, whereby the constructor performs only essential and exception-free initialization operations such as zeroing data members, and a separate member function later performs additional initialization steps that might throw.

Question: Can I use a function try block to catch exceptions from an ordinary function?

Answer: Yes, you can. However, you always have a better choice, namely replacing the function try block with traditional exception handling. Consider:

void f()
try  //function try block
{
}
catch(exception &e)
{
}

When dealing with regular functions, you always have the option of wrapping the exception handling code with braces, effectively transforming the function try block into a traditional try block:

void f()
{ //added
 try
 {
 }
 catch(exception &e)
 {
 }
}//added

The second problem with regular functions is that you can't return a value from a function try block handler. Therefore, if your function has a return value other than void, you can't use function try blocks at all:

int g() //error
try
{
   ...
}
catch(exception &e)
{
 //can't return a value from a handler!
}

In Conclusion

Although theoretically function try blocks aren't confined to constructors with member initializers, they aren't useful in other contexts. In some cases, e.g., main(), the C++ standard prohibits the use of function try blocks. In other cases (destructors, regular functions) it's technically possible to use function try blocks but their usefulness is moot.