Boost logo

Boost Users :

Subject: Re: [Boost-users] [Test] Making use of boost::exception_diagnostic_information and friends
From: Gennadiy Rozental (rogeeff_at_[hidden])
Date: 2009-08-10 20:37:32


Emil Dotchevski wrote:
> On Mon, Aug 10, 2009 at 2:58 PM, Gennadiy Rozental<rogeeff_at_[hidden]> wrote:
>> Emil Dotchevski wrote:
>>> 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(...).
>> I do. I hoped I can handle throw foo() in catch( foo ) and
>> BOOST_THROW_EXCEPTION( foo() ) in catch( boost::exception ). Former would
>> not try to dig inception point info. Later would.
>>
>> Actually I might want to do it in all clauses after all. I do want to be as
>> specific as possible. An alternative is to somehow deduce type at runtime in
>> generic catch boost::exception clause, but this seems non reliable.
>
> I might not be understanding exactly what you're doing. In my mind, a
> testing framework should assume that (unless you're testing exception
> handling) any exception a test emits is unexpected, and then the only
> useful thing you can do is log some diagnostic information; I don't
> see a need for anything more than
>
> catch(...)
> {
> std::cerr << boost::current_exception_diagnostic_information();
> }

Does this require some kind of RTTI?

> Here is an example of what this could display:
>
> example_io.cpp(83): Throw in function class boost::shared_ptr<struct
> _iobuf> __cdecl my_fopen(const char *,const char *)
> Dynamic exception type: class
> boost::exception_detail::clone_impl<class fopen_error>
> std::exception::what: example_io error
> [struct errno_ *] = 2, OS says "No such file or directory"
> [struct file_name_ *] = tmp1.txt
> [struct function_ *] = fopen
> [struct open_mode_ *] = rb

1. This is not very readable at best?
2. What if I want to generate XML log instead?
3. What if I do not want to display anything at all, but store in some file?

My general comment to this: boost::exception (and execution_monitor for
that matter) is too low level component to make these decisions. Proper
library design should not force any decisions on the user.

> By the way in some IDEs double-clicking the first line in the above
> message will open the source location in the editor.

What if I use different IDE which uses file:line instead?

>>>> 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
>> I need to report the error somehow, don't I? Including all the details.
>
> Yes, and in my mind "all the details" are included in the string
> returned by boost::current_exception_diagnostic_information. If
> anything useful is missing from that string, then it should be
> included instead of doing something else.

It is too rigid. Aside from the fact that the function returns int.

>>> 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()));
>>> }
>> I do not see why I need BOOST_THROW_EXCEPTION. I do not care about this
>> exception inception point. I know it ;) Also I throw this exception in all
>> cases when an error occurred (for example in case if signal triggered). It
>> operates on strings and numbers.
>
> Sure, you can throw any exception without BOOST_THROW_EXCEPTION.
> However there's virtually no overhead in using BOOST_THROW_EXCEPTION.
> It does not allocate memory, yet allows users to add arbitrary data in
> the exception and to get a boost::exception_ptr to it.

I do not need to add any data. I just need to return one that I have ;)
And I may not have "original" exception as well.

>>>>> 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.
>> But If I already have catch( boost::exception ) I should not try to dig this
>> info in catch(...) right?
>
> In this particular case, what would you do with a boost::exception
> that's different from what you'd do with any other exception in a
> catch(...)?

After some testing it seems that BOOST_THROW_EXCEPTION only works with
types inherited from std::exception.

This means that I do not need separate boost::exception clause at all.

catch (...) will never be invoked with boost::exception (cause I have
catch std::exception), thus I do not need to deal with digging inception
location there.

>>>> 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).
>> What is the requirement on type of e? can it be char*? Or std::string?
>
> e is the exception you catch. Here's how you use it:

This is not what I asked. It seems the answer is no for both.

>> Can we have something like 'cause', which will be the same as
>> diagnostic_info, but without inception point?
>
> For what reason? It seems to me that you're trying to make the
> returned string "prettier" which is unrealistic.

I do not believe so. Simplest 'cause' implementation can just forward it
to the std::exception::what.

> The string is pretty
> much guaranteed to be ugly to look at yet rather informative. :)

I believe you gave up too early. You should not take over formatting of
the error messages (you can provide default I guess)

> That said, I do agree that especially if you're generating some kind
> of xml report, processing the location of the throw specifically is a
> good idea.

Yep. This is my intention.

An implementation of boost::exception support is checked in (revision
55515). Please take look and let me know if you see any issues with it.

Gennadiy


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