std::auto_ptr as exception object

J

j.l.olsson

Hello,

I am using std::auto_ptr to try to keep ownership of resources
straight. However, I became aware that exception objects must provide
a copy constructor, which made me uncertain of the soundness of
throwing std::auto_ptrs...

It was explained to me that a possible problem case is:

try {
throw std::auto_ptr<int>(new int(10));
} catch (std::auto_ptr<int> a)
{
throw;
}

If I understood correctly, the re-throw would use the original
exception object, which has lost ownership.
Is there a way to prevent catching by value?
Is catching by reference kosher?
Are there other problems with throwing auto_ptrs?

Thanks.
 
I

Ian Collins

Hello,

I am using std::auto_ptr to try to keep ownership of resources
straight. However, I became aware that exception objects must provide
a copy constructor, which made me uncertain of the soundness of
throwing std::auto_ptrs...
Why on Earth would you want to?
 
E

ejstans

Why on Earth would you want to?

Use auto_ptr or throw exceptions containing them?
Well, for the latter, kind of for the same reason one would want to
pass them as functions parameters I suppose?

In my case, let's say I have an auto_ptr'ized Msg object. Depending on
certain conditions it will be passed to different methods to do
various operations on it, and if successful it will be sent off to
other places and won't be of concern anymore. But if failure occurs
for some reason, the idea was to throw an exception and catch this in
the original place so that a different method can have a go at it.
Because of auto_ptr's ownership policy, somehow the Msg must also be
passed back. I thought it desirable to keep it auto_ptr'ized, but then
I realized there is cause for concern of putting the auto_ptr in the
exception...
 
M

Marcel Müller

Hi!

I am using std::auto_ptr to try to keep ownership of resources
straight. However, I became aware that exception objects must provide
a copy constructor, which made me uncertain of the soundness of
throwing std::auto_ptrs...

It was explained to me that a possible problem case is:

try {
throw std::auto_ptr<int>(new int(10));
} catch (std::auto_ptr<int> a)
{
throw;
}

If I understood correctly, the re-throw would use the original
exception object, which has lost ownership.
Is there a way to prevent catching by value?

Is catching by reference kosher?
Yes.

Are there other problems with throwing auto_ptrs?

Besides the fact that it does not make sense? - Not that I know.

The lifetime of an exception object is managed by the compiler. You need
not to bother about that.
In your case
throw 10;
would do the job too. The same applies to almost any exception class.

Simply do not write throw new..., that's a job for Java programmers. And
I also recommend to receive constant function arguments by reference if
their copy-constructor is more complex than that of a built-in type.
That applies also to exception arguments.


Marcel
 
J

James Kanze

I am using std::auto_ptr to try to keep ownership of resources
straight. However, I became aware that exception objects must
provide a copy constructor, which made me uncertain of the
soundness of throwing std::auto_ptrs...
It was explained to me that a possible problem case is:
try {
throw std::auto_ptr<int>(new int(10));
} catch (std::auto_ptr<int> a)
{
throw;
}
If I understood correctly, the re-throw would use the original
exception object, which has lost ownership.
Is there a way to prevent catching by value?
Is catching by reference kosher?

It's the usual practice, since it takes polymorphism into
account.
Are there other problems with throwing auto_ptrs?

Well, the copy constructor takes a non-const reference, so you
cannot copy a temporary. (In other words, your example
shouldn't compile---although I couldn't find a compiler which
rejects it.)

The usual practice would be to throw by value, and catch by
const reference:

try {
throw 10 ;
} catch ( int const& err ) {
throw ;
}

(Of course, you almost never throw int's. In practice, you'd
throw some specific class derived from std::exception.)
 
E

ejstans

Thanks for the replies!
It seems my example somehow was a bit confusing. It was a distilled
illustration that I thought would get to the heart of my problem (ie,
is it possible to safely to throw auto_ptr) but it seems it's maybe
best to describe a little bit more about my specific situation:
The usage is as described in my follow-up post above.
I have an exception class derived from std::exception that was to take
over ownership of the Msg object (created long ago), for the purpose
of transporting it to the relevant error handling code. The form of
the ownership was to be an auto_ptr, since that's used elsewhere and
naked pointers are preferably avoided. I'm not married to this design,
and would gladly change it for something better, but at the moment I'm
content to understand the exact behaviour of throwing auto_ptr, not
whether doing so necessarily makes sense in a grander scheme of life.
 
E

ejstans

* (e-mail address removed):



It's clearly the intentention of that standard that an exception object must be
copy constructible. For example, §15.3/1 tells us that if a handler declares a
non-const exception object, changes to that object do not affect the temporary
that was created by the throw statement. While the copy constructible
requirement is (unfortunately) not spelled out, you should simply regard it as
an error to throw any object that is not copy constructible.

std::auto_ptr is not copy constructible.

And this causes MSVC 7.1 to emit a spurious warning when throwing a
std::auto_ptr, which warning should be taken very very seriously.

Thanks. This kind of answer was exactly what I was hoping for, and
I've banished
auto_ptr from my exception object.
 
K

Kai-Uwe Bux

Alf said:
* (e-mail address removed):

It's clearly the intentention of that standard that an exception object
must be
copy constructible. For example, §15.3/1 tells us that if a handler
declares a non-const exception object, changes to that object do not
affect the temporary that was created by the throw statement.
[snip]

You might be right about the intention of the standard, but I am not
convinced by that example. To me, it appears more likely that this
provision aligns catch-syntax and function call syntax. The same clause
says that if you catch by non-const reference, changes to the object will
be reflected in the original temporary. It seems that no copied of thrown
object will be created if you always catch by non-const reference.


Best

Kai-Uwe Bux
 
J

James Kanze

* Kai-Uwe Bux:
The throw itself copies, via copy constructor (but the problem
is that "copy constructor" can be T(T&), thus not excluding
auto_ptr & like classes).

But that does mean that you can't throw a temporary auto_ptr.
The original example was:
throw std::auto_ptr< T >( new T ) ;
(or something like that), the std::auto_ptr here is an rvalue,
and cannot be bound to a non-const reference.

(For the rest, I think you're totally right that the intent is
clearly that anything thrown be copiable---or CopyConstructible,
as the library parts of the standard call it.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,782
Latest member
ThomasGex

Latest Threads

Top