Boost logo

Boost :

Subject: Re: [boost] Boost and exceptions
From: Robert Ramey (ramey_at_[hidden])
Date: 2012-06-23 15:11:33


John Maddock wrote:
>> Why does the serialization library have to include code from boost
>> exception in order to do this?
>>
>> You can use boost exception at the same place, catch
>> the standard exception that the serialization throws, construct
>> you're own boost exception and continue on.
>
> No!!!!
>
> Misses the whole point - Boost.Exception allow you to annotate an
> existing exception without loosing the original information - and
> that includes the *type* of the original exception.

Here is what I don't get.

When the serialization code was written I
decided that the exception mechanism was that right way to go.
I realized that just a "generic" exeception wouldn't included enough
information so I created boost::archive::exception and extra data
specific the this kind of acception. The file name is
archive_exception.hpp. This exception type has most of the
useful information regarding the exception. Some was excluded
as it would make the type "heavier" than I wanted or would
have required data types which might use the heap or other resources
which of course would be a disaster. It also was carefully designed
not to include RTTI and other stuff which would make the library
less attractive for lighter weight applications. Basically this was
designed as the best balance among all the considerations I had to
take into account - including the desire to pass as much information
as possible to the application.

I also used boost::throw_exception in order to permit the system
to gracefully handle the case where exception were either not
available or not permited in the user environment. boost::throw_exception
was explicilty designed for this purpose and no other.

So - boost::throw_except is changed and.... what? I already included
all the useful information I can add. How can boost::throw_exception
add to this on it's own? What can it possible do that's useful? The
archive_exception is already derived from the standard base class
so it can be caught by catch(std::exception e &). It's derived virtually
from std::exception so the e in can be downcast to the archive_exception
and get all it's data. If the user want's to, he has the option or using
rtti type_id to get the type - but he's not forced to if he want's to
keep his code lean and mean.

To summarize, I don't see how just changing boost::throw_exception
without changing anything else can possible add anything useful to
the library or the users application.

> Consider writing a future - in order to preserve all the exception
> information, you would have to be able to catch, clone, and then
> rethrow *every possible exception type* that may be thrown by the
> code that the future calls. It is quite simply impossible.

> However, if all thrown exceptions inherit from boost::exception, then
> you simply catch that exception type, ask it to clone itself, and
> rethrow in a different thread. You preserve all the original error
> information, and crucially, all the original type information, even
> though the future doesn't itself know what the actual dynamic type of
> the caught and rethrown exception is.

Hmmm - I don't see how just changing the implementation of
boost::throw_exception would change this in anyway. Perhaps you're
suggesting that in addition to chaning the functionality of boost::throw
the serialization libary should redefine archive_exception to derive
from boost::exception rather directly from std::exception. Of course
that's a totally different topic than we've been discussing up until now.
and I guess would be a new thread. But maybe you're not suggesting
that. Sorry if I got this wrong.

Still, you're question obligated me to think a little about this. I would
expect a library such as boost exception would have code along
the following lines somewhere to be included/invoked from user
code.

void * x
x = dynamic_cast<boost::exception be *>(std::current_exception())
if(0 != x){
    ... // do great boost exception stuff
}
else {
void * x = dynamic_cast<std::exception be *>(std::current_exception());
    .. // use what() and do some stuff
}
else{
    // handle the case where the library, user didn't bother to use
std::exception
}

But this is totally compatible with the original implementation of
boost::throw_exception!

So it looks to me that changing the functionality of boost::throw adds
nothing
to libraries which don't use boost::exception.

Even if libraries are changed to use THROW_BOOST_EXCEPTION the
only thing added is file # / line # - I havn't heard any users clamoring for
that.

Finally, any users who want real information on the exception will have to
include archive_exception.hpp in any case. True it make users think they are
"handling" something - but if there's not catching archive_exception and
dealing with the specifics, they might as well use std::exception.
So I don't see that boost exception actually adds anything of any value.

> This actually looks compelling enough to me, that we should probably
> mandate use of BOOST_THROW_EXCEPTION.

lol - right.

>> My complaint is the process by which it was inject.
> Fair enough, but you're still 4 years too late on that one.

lol - well I wasn't late when I brought it up the first time. It was right
at release time when this bomb was dropped in at the last moment.

> I repeat an earlier question - if Boost.Exception were refactored to
> put the "core" exception throwing code either into boost/detail/ or
> indeed directly into boost/exception.hpp given that there's not much
> of it, would that address at least some of your concerns?

I don't get this. Wouldn't this still drag in hundreds of lines of code
that aren't being used?

>> BUT - now you've sucked me into looking at the merits of including
>> it, I don't
>> see that it would be of any use. here's typical serialization code:
>>
>> #include <boost/archiive/binary_iarchive.hpp>
>> #include <ifstream>
>> ...
>> f(...){
>> ifsteam is("my file")
>> binary_iarchive ia(is);
>> try {
>> my_data d;
>> ia >> d;
>> }
>> catch(boost::archive::exception ae){
>> std::cout << ae.what();
>> throw(ae) ; // or throw something else
>> }
>> return;
>> }
>>
>> So if I want to use boost exception I would just write
>>
>> #include <boost/archiive/binary_iarchive.hpp>
>> #include <ifstream>
>> #include <boost/exception/???.hpp>
>> ...
>>
>> f(...){
>> ifsteam is("my file")
>> binary_iarchive ia(is);
>> try {
>> my_data d;
>> ia >> d;
>> }
>> catch(boost::archive::exception ae){
>> std::cout << ae.what();
>> // I don't know how to use boost::exception insert your own
>> code here
>> boost::exception::throw(?)
>> }
>> return;
>> }
>>
>> I don't see injecting boost::exception into the serialization code
>> changes this in
>> any way
>
> Please see my answers above.

I still don't see how boost exception helps in my example. If you don't care
about handling archive_exception you can just use

ifsteam is("my file")
binary_iarchive ia(is);
    my_data d;
     ia >> d;

and just handle std::exception upstream. If you really like
boost::exception
your code when you eventually can eventually rethrow

catch (std::exception e){
    BOOST_EXCEPTION_THROW_EXCEPTION(e)
}

> Now consider that the serialization code includes some use of
> Boost.Filesystem, Boost.Regex (filename parsing) and heaven known
> whatever other dependencies the object being [de]serialized depends
> on (presumably an object being deserialised could throw any exception
> Boost is capable of). If all those exception objects uniformly derive from
> boost::exception
> somewhere in their object hierarchy, then you catch *one* exception
> type, annotate it, and rethrow. All the original type information is
> retained, clients can catch the boost::exception and enumerate all
> the information it holds, or they can catch something more specific
> like boost::archive::exception and work from there.

How is this different from using std::exception ?

> I admit to being new to what boost::exception has to offer, but that
> looks pretty compelling to me,

Sorry john, I'm still not seeing it. You'll have to dumb it down for
us mortals.

Robert Ramey

>
> Cheers, John.
>
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost


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