Boost logo

Boost Users :

Subject: Re: [Boost-users] [Test] Making use of boost::exception_diagnostic_information and friends
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2009-08-10 16:41:45


On Mon, Aug 10, 2009 at 11:45 AM, Gennadiy Rozental<rogeeff_at_[hidden]> wrote:
> Emil Dotchevski <emildotchevski <at> gmail.com> writes:
>> >> Since the testing framework wouldn't know anything about the
>> >> exception
>> >> it's reporting, it should catch(...) and leave it up to
>> >> current_exception_diagnostic_information to provide all the
>> >> information it can dig out from whatever the current exception may > >>
>> >> be.
>> >
>> > 1. It will never get to the catch(...) execution monitor has tons of > >
>> > other catch
>> > clauses (including catch (std::exception)) which will trigger first.
>>
>> So you could do:
>>
>> catch( foo & e )
>> {
>>     //do other stuff, and then:
>>     std::cerr << boost::diagnostic_information(e);
>> }
>> catch( boost::exception & e )
>> {
>>     //do other stuff, then:
>>     std::cerr << boost::diagnostic_information(e);
>> }
>
> 1. Isn't supposed to be other way around: first catch boost::exception,
> followed
> by catch foo? I'd prefer to have boost:exception related logic in a single
> catch
> clause instead of being spread between 20.

I was implying that you normally catch more specific exceptions first.
If you don't care about foo in particular you can use a generic catch
like catch(boost::exception/std::exception) or catch(...).

> 2. I do not want to print anything. I collect information and return it (by
> throwing another exception) to the higher level, which in turn decides how
> and
> where to report it.

I don't see the point of throwing another exception but if that's what
you want to do then you could use boost::exception_ptr:

catch(...)
{
  BOOST_THROW_EXCEPTION(another_exception(boost::current_exception()));
}

Later on, when you catch(another_exception &), you can pass the stored
exception_ptr to boost::diagnostic_information, and you'll get
diagnostic information about the exception it holds (the one captured
by boost::current_exception() in the original catch(...)). Or you can
rethrow it and use suitable catches to handle it.

>> catch( std::exception & e )
>> {
>>     //do other stuff furst, then:
>>     std::cerr << boost::diagnostic_information(e);
>> }
>> catch( ... )
>> {
>>     std::cerr << boost::current_exception_diagnostic_information();
>> }
>
> What is the point of trying to dig something here? Wouldn't the
> boost::exception based exception will always be caught in 'catch
> boost::exception' clause above?

If all you do is get diagnostic_information, then just the catch(...)
is sufficient.

>> > 2. execution monitor is very careful about memory being used. How
>> > about diagnostic_information?
>>
>> You'd have to define the meaning of 'careful' :) but if you're asking
>> how much memory diagnostic_information allocates, it simply composes a
>> std::string which it returns to the caller.
>
> execution_monitor does not allocate memory at all in the point of error
> processing.

In fact the act of throwing an exception allocates memory which comes
from the heap in many implementations but anyway, I hope you're not
proposing that diagnostic_information returns something other than a
std::string :)

>> > 3. I pretty much only need file, line and function name. Are you
>> > saying I can't do what you are doing inside diagnostic information
>> > to get a hold of them?
>>
>> If the exception was thrown by BOOST_THROW_EXCEPTION, then yes you'd
>> have file, line and function name.
>
> Ok. So how do I do this?

Use get_error_info<throw_function>(e), get_error_info<throw_file>(e),
get_error_info<throw_line>(e).

>> However, objects that derive from
>> boost::exception can have data of arbitrary type, some of it added at
>> the point of the throw, some of it added later (meaning, it depends on
>> the callers of the function that throws.)
>>
>> Do you not want to display all that information when you catch a user
>> exception in the testing framework?
>
> I do not mind if method 'what' would generate "rich" error message including
> everything, but the information about the point of inception (Or some other
> method)

The problem with what() is that some programmers use it to return a
user-friendly message. This is incorrect because in general
user-friendly messages have to be localized which clearly goes beyond
what()'s interface. Boost::diagnostic_information has clearer
semantics: the string it returns is not user-friendly; it has any and
all information that might be useful for diagnostic purposes, which
also includes the output from what(), the file/line/function
information, anything added to a boost::exception through operator<<,
etc. At BoostCon there was some interest in adding stack trace to
boost::diagnostic_information too. In principle, anything that is
known about the exception should be included.

Emil Dotchevski
Reverge Studios, Inc.
http://www.revergestudios.com/reblog/index.php?n=ReCode


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net