Boost logo

Boost :

Subject: Re: [boost] Boost and exceptions
From: Sebastian Redl (sebastian.redl_at_[hidden])
Date: 2012-06-24 07:48:06


On 24.06.2012, at 01:19, Robert Ramey wrote:

> Emil Dotchevski wrote:
>> On Sat, Jun 23, 2012 at 12:11 PM, Robert Ramey <ramey_at_[hidden]> wrote:
>
>> For example, if Boost Serialization calls boost::throw_exception, an
>> application that serializes data that comes from a web site could
>> store the web address, the user name, port number, or whatever else
>> the application needs to handle the exception.
>
> the serialization libary will likely not have this information. Geneally
> the serilalizaiton library uses some sort of stream i/o object. Many
> times errors are detected in the stream. At this point, the none
> of the library knows what the file name is so it can't be added
> in until some way higher level. The current archive_exception
> class holds all the useful information which is available.

And boost::exception allows the surrounding code to add the information that wasn't available to the serialization library. That's the whole point!

>
>>> your code when you eventually can eventually rethrow
>>>
>>> catch (std::exception e){
>>> BOOST_EXCEPTION_THROW_EXCEPTION(e)
>>> }
>>>
>>
>
>> Second, even if you catch std::exception & obj, throwing obj will
>> slice, erasing the dynamic type of the original exception.
>
> It's hard to see the slicing through the macro

The slicing assumption is there by default because C++ cannot do any better. The only way to avoid slicing would be to enumerate all possible dynamic types that could possibly be thrown here. Given that user-defined types can throw user-defined exceptions while deserializing, this is somewhere between "extremely difficult and fragile to far-off code changes" and "impossible".

>
> isn't the standard way of handling this better?
>
> catch(std::exception & e){
> std::exception_ptr e = std::current_exception();
> std::rethrow_exception(e);
> }

This doesn't do anything. What are you trying to achieve?

>
> or if you want to add your own sauce
>
> catch(std::exception &e){
> std::exception_ptr e = std::current_exception();
> someclass se(e, extra stuff); // home brew or from some library
> std::throw(se);
> }
>
> or if you want to catch anyone's stuff
>
> catch(...){
> std::exception_ptr e = std::current_exception();
> my_unknown_exception me(e); // though its not clear what the upper level
> could do with this
> }
>
> this would confine the usage of boost exception to areas where the user
> can decide whether or not he want's to use it. It looks to me that the
> standard
> was conceived to support just this usage. It doesn't require anything
> special at the
> throw point. The standard facility of using one's own exception class is
> sufficient.

As Steven pointed out, it isn't. You lose type information. Using your own exception class that contains an exception_ptr (or using std::throw_with_nested) is fine if you want to do true translation of the exception, but not if you want to preserve the original exception (so that catch sites can refer to the original type). It's the way the C++ exception system works: the only point where full type information is statically available is at the throw site. This is why Boost.Exception has to hook that point, and not anything else.

> lol - well you've got a point here. But I not convinced a huge problem in
> practice.
> I would expect most of these would be placed at the much higer levels.

Not if the point is to enable boost::exception support and thus allow additional information to be attached.

Also, enumerating types is, as I mentioned, extremely fragile. Do you absolutely promise not to ever throw something that derives from archive::exception instead of that class itself? Did you document this promise in your library? Did you document that no library extension functionality must throw anything but plain archive::exception objects or else have a big fat warning in their documentation?
If you didn't, then I can't catch your exception and add boost::exception functionality. You have to do it.

>
>>> How is this different from using std::exception ?
>
>> You can't add your own stuff to a live std::exception.
>
> I believe equivalent functionality is available.

You're wrong about this.

Sebastian


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk