Tuesday, February 28, 2012

New Rules for a New Era

As I write this it’s 2012.  There’s a new C++ standard, C++11, and yet I still come across a lot of bad C++ code in the wild.  So I decided to use some of my time to write some posts that I hope new programmers will find and use to improve their skills.  Today I’m going to talk about a “rule” I found on a blog post from 2007 that was one of the top results when I searched the web for information about exceptions.

The rule is:

Avoid exceptions.  Exceptions will only leave you open to the memory and resource leaks. Don't use them. The exception to this rule is if you are programming in a style that doesn't use pointers, and everything is encapsulated into smart pointers.

The problem I see is the exception to the rule that should be the standard programming style followed.  There is rarely a need to program in a style that uses bare pointers.  Even when you need to use a bare pointer the standard library has facilities to make them exception safe.  The example given in the posting was:

void foo()
{
    Object *obj = new Object();
    bar();
    delet obj;
}

As you can see if bar() throws an exception the instance of Object is not released and we have a resource leak.  This is used as the argument of why we shouldn’t use exceptions.  I counter that this is an example of poor coding.  I would recommend two ways to rewrite the foo() function that remove the resource leak.

The first method would be to declare the instance of Object on the stack.  If an exception is thrown the resources would be released when the stack is unwound as part of the exception processing.  If Object contains large data members they should be allocated on the heap as part of construction and released during destruction.  This would change foo() to:

void foo()
{
    Object obj();
    bar();
}

The second method would be to use std::unique_ptr<> which would wrap the instance of object allocated on the heap with new.  The instance would also be released when the stack is unwound during exception handling as the wrapper includes a destructor to free the resource.  This version of foo() would be:

void foo()
{
    std::unique_ptr<Object> obj(new Object());
    bar();
}

I mentioned before it was 2012.  Microsoft Visual C++ 2010 has support for some C++11 features and std::unique_ptr<> is one of them.  So stop using bare pointers unless you have a real need for them, and I’ll bet that you do not have a real need for them.