Emil Dotchevski wrote:
On Mon, Aug 10, 2009 at 2:58 PM, Gennadiy Rozental
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
(e), get_error_info (e), get_error_info (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