|
Boost : |
From: Emil Dotchevski (emil_at_[hidden])
Date: 2007-09-30 20:23:48
> > <snip>
> > Sure, there are use cases when you know an error_info must be present
> > in the exception or you have a bug, but in that case it makes more
> > sense to assert on get_error_info.
> >
>
> Far from it. I'm thinking get_error_info(T const &) should not compile
> if the error_info being requested has not been passed to the
> exception.
I don't think this is possible. Consider that a main design goal of
boost::exception is to be able to do this:
try
{
---something---
}
catch( boost::exception & x )
{
x << error_info<my_info>(....);
throw;
}
In general, when we finally catch the exception object, it may have
my_info or not.
> At any rate, perhaps using something like Boost.Optional as the return
> value (or an additional parameter to get_error_info) mitigates the
> problem you describe. Somehow, for me the following reads a bit more
> coherent if not safer:
>
> try {
> ...
> } catch (boost::exception & e) {
> boost::optional<int> errno = boost::get_error_info<tag::errno>(e);
> if (errno) { // means errno is set
> cerr << *errno;
> } else { // means errno is not set, then set it
> e << boost::error_info<tag::errno>(-1);
> };
> throw; // propagate exception
> };
Would you agree that this is simpler and easier to read?:
try {
...
} catch (boost::exception & e) {
if( int const * ec = boost::get_error_info<tag_errno>(e) ) {
cerr << *ec;
} else {
e << boost::error_info<tag::errno>(-1);
};
throw; // propagate exception
};
> <snip>
> It's good to know that you haven't had any performance-related issues
> with this library. I'll take your word for it.
>
> However, a shared_ptr<> implies allocating something on the heap.
>
> Anytime you make an (arguably) unnecessary memory allocation in the
> heap, in my book is a performance affecting issue. We can go on and
> argue about long jumps, cache misses, and memory locality issues, but
> this would be moot since the goal of the library is primarily to
> provide a functionality that seems to require the heap allocation *by
> design*.
In the particular case of Boost Exception, any speed overhead it adds
should be compared to the overhead of throwing an exception. You have
stack unwinding and destructor calls, etc. anyway. I don't think that
optimizing Boost Exception for speed makes any sense.
Optimizing the memory allocations made by Boost Exception when info is
added to exception objects can not be dismissed as easily, but I would
not call those allocations unnecessary. :)
Consider that all of these allocations happen immediately before or
during stack unwinding, and at that time the rest of the code doesn't
usually allocate memory. When the exception is finally handled, all
this memory is reclaimed, and assuming that no other memory was
allocated during the stack unwinding, we don't get fragmentation
either.
> > > My concern with the use of shared_ptr<>'s is that in cases where an
> > > exception pertaining to "out of memory" conditions would arise,
> > > throwing a boost::exception and then having to allocate more memory
> > > just to encapsulate additional information would lead to undesirable
> > > termination.
> >
> > Could you elaborate a bit more? Can you come up with a theoretical
> > example that demonstrates your concerns?
> >
>
> Theoretically, (or I think even in reality) a call to the (default)
> new operator may trigger a bad_alloc exception. This exception may be
> caught, and somewhere along the way code decides to encapsulate the
> information in that bad_alloc exception into a boost::exception -- and
> chooses to say where that exception happened, as a tag in the
> propagated boost::exception.
I guess I should have been more specific, could you elaborate how
using boost::exception would "lead to undesirable termination"?
Emil Dotchevski
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk