3

Is it safe to use unique_ptr? When I use cout in destructor, sometimes it called more then one time. - so it make copy time-to-time. if it take two copy from one object - data can be lost..

#include <memory>

class MyException
{
    std::unique_ptr<Type> data;

    MyException();
    ~MyException() {cout<<"test"<<endl;}

    MyException(MyException ex&);
};

int main()
{
    try
    {
        try
        {
            throw MyException();
        }
        catch (const MyException& ex)
        {
            throw;
            //or?
            throw ex; //will be copied?
        }
    return 0;
    }
    catch(const MyException/*& will be missed. will ex be copied?*/ ex)
    {
        throw; //wich ex will be re-throw, copy or original?
        //or?
        throw ex; //will be copied?
    }
}

Can I be sure, that data will not be lost between re-throws? And is this good practic to use ptr inside exception to collect error info from different levels?

Also, can MyException.data be lost after:

std::exception_ptr ex =  std::current_exception();
std::rethrow_exception(ex);
Darida
  • 196
  • 1
  • 8
  • 1
    Rethrowing doesn't make copies; that's guaranteed. However, there may be other points at which is unspecified whether a copy is made. – Kerrek SB Jul 05 '13 at 09:49
  • vs 2012. with "throw;" - 1 "test" in output. with "throw ex;" - 2 "test" in output. 2 destructor = 2 object... => copy was made. – Darida Jul 05 '13 at 10:30

2 Answers2

1

As you discovered, you should always say throw; when you want to re-throw an exception, not not throw ex;. Indeed, throw ex; will copy (and slice, if ex is a reference to a base class!).

So, always catch by reference, and always re-throw without naming the exception.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
0

With gcc 4.7.3 your example doesn't compile, complaining about a missing copy constructor for MyException. This is in the line where it's first thrown, so throw MyException() itself already wants to make a copy (at least in gcc). See also this stackoverflow question and the C++ FAQ.

To answer your question about whether using pointers in exceptions is good practice, I would generally say no. Unless the data to be piggybacked onto the exception is huge (which would likely be a design problem), a stack allocated data structure should be preferred. Performance shouldn't be the main concern during exception handling anyway, so copying stuff around isn't a real problem.

If you really need a pointer (maybe Type has no copy constructor and you can't change that), using shared_ptr could help you in a pinch, although I feel like that would be an ugly hack. I would probably try and reduce the information passed via the exception to the bare minimum that would help callers identify and handle the problem.

Edit: I found the relevant section in the C++ standard, section 15.1, paragraph 5:

When the thrown object is a class object, the copy/move constructor and the destructor shall be accessible, even if the copy/move operation is elided.

So it's actually not legal C++ to throw an exception object without a copy constructor.

Community
  • 1
  • 1
Benjamin Kloster
  • 362
  • 1
  • 2
  • 13