views:

152

answers:

1

The C++ Standard, paragraph 15.1.4 sais:

The memory for the temporary copy of the exception being thrown is allocated in an unspecified way, except as noted in 3.7.3.1. The temporary persists as long as there is a handler being executed for that exception.

I'm wondering why this code crashes (I know that it's not best practice):

class magicException
{
private:
    char* m_message;

public:
    magicException(const char* message)
    {
        m_message = new char[strlen(message) + 1];
        strcpy(m_message, message);
    }

    ~magicException()
    {
        cout << "Destructor called." << endl;
        delete[] m_message;
    }

    char* getMessage()
    {
        return m_message;
    }
};

void someFunction()
{
    throw magicException("Bang!");
}

int main(int argc, char * argv[])
{
    try
    {
        someFunction();
    }
    catch (magicException& ex)
    {
        cout << ex.getMessage() << endl;
    }

    return 0;
}

Specifically, the destructor of the thrown magicException object gets called before the catch block. If I however add a copy constructor to my class:

magicException(const magicException& other)
{
    cout << "Copy constructor called." << endl;
    m_message = new char[strlen(other.m_message) + 1];
    strcpy(m_message, other.m_message);
}

Then the code works, the destructor gets called at the expected place (the end of the catch block), but interestingly the copy constructor still doesn't get called. Is it optimized away by the compiler (Visual C++ 2008 with optimizations turned off), or am I missing something?

+3  A: 

Specifically, the destructor of the thrown magicException object gets called before the catch block.

Yes, as your quote from the standard says, a copy is taken by the compiler, and the original (probably) discarded. Your problem is the lack of a copy constructor in your original code. However, a C++ compiler is allowed to remove (or add) copy constructor calls in all sorts of situations, including this one.

anon
I have added a copy contructor (see my post), but it's not being called. My question is, why doesn't the copy constructor get called.
Stefan Schultze
See my edit - copy constructor calls may be elided by the compiler, even if they have side effects.
anon
Thank you, I've found an article clarifying this: http://en.wikipedia.org/wiki/Return_value_optimization#Other_forms_of_copy_elision
Stefan Schultze
@Stefan: Use -fno-elide-constructors (g++) to turn that optimization feature off.
Prasoon Saurav
@Prasoon His question says he is using VC++
anon
@Neil: Is there a similar command available in MSVC++ to turn that feature off?
Prasoon Saurav