Den 23. aug. 2013 kl. 12:06 skrev Andreas Lauser:

[...]
(for example, a Newton solver not converging is not an exceptional thing).

That's a thing I see quite differently. The reason is that there are about a
million things which could go wrong that make the newton solver diverge. If
any and all of this cases is protected by a classical "if(error) return
error;" guard, you take quite a performance hit (by means of the guards
themselfs and by means of missed optimization opportunities). On the other
hand, C++ exceptions do not negatively impact performance (for details, see
http://stackoverflow.com/questions/13835817/are-exceptions-in-c-really-slow ).

Semantics first: a Newton solver failing to converge is something that should be
expected, and to a large extent any reasonable software must handle the 
possibility.
Therefore it is not exceptional, and the event should not be hidden from the 
API.

Performance: only when not being thrown can C++ exceptions have no overhead.
Modern compilers will emit code that cause no performance penalty when nothing
is thrown, but if an exception is thrown it will have major performance 
consequences.
This is quite all right usually, but it means that any code that uses 
exceptions for
non-exceptional things, as alternative control flow, is going to be slow.



So over time I gravitated towards the approach followed now in most of the
software I have made -- report errors with the THROW(something) macro from
ErrorMacros.hpp. This just sends file and line number plus the 'something'
part to std::cerr, and throws a pure, unadorned std::exception.

I also have a slightly different opinion about that. IMHO it is okay to encode
some information in what the error was within the exception object. I think of
this as a modern version of the old-school C 'errno' variable.

I can agree that a little context in the exception object does not hurt (I did
characterise my approach as a somewhat extreme after all…).


It could be argued that this is somewhat extreme in its lack of information
being transmitted with the exception, but my reasoning is as follows: most
of the time, the context of the exception is important for debugging, and
this cannot be carried by the exception.

punching 'catch throw'  into GDB makes it break whenever an exception is
thrown. this is a thing that is very hard to do for the traditional way. Also,
if more complicated breakpoint conditions are required, putting
'raise(SIGINT);' into your code makes GDB break at this location. For these
reasons I think think exceptions are not hard to debug. (That is, of course,
if you don't use them as a normal return mechanism.)

This is fine for a developer, but not for an end user. Trying to explain 
debugging
in gdb to someone at a client company who just encountered a fatal error is not
a good use of either's time.


That is why the macro prints file
and line number. On the other hand, the receiving end is rarely implemented
(other than, perhaps at a very high level), and would not be able to use
this information anyway.

This might be true for opm-core and opm-porsol, but eWoms catches
'NumericalException' and tries again with a smaller timestep. As you can
imagine, is a relatively common case.

This may be a performance bomb, see above. Even if it turns out to not be,
it is in my opinion abusing the exception concept, since it is an unexceptional
event. Finally, if you really want to use a specific exception for this, it 
should
be something like NewtonFailureMaxIter or something like that.


Introducing a new exception hierarchy is of dubious value. I think that once
you has digested the appropriate usage of the standard range_error vs.
out_of_range_error vs. invalid_argument vs. length_error and so on (quick
quiz: what is appropriate for an index check in an array), you will not
feel the need to complicate any further. If one feels the need for
specialty exceptions that is fine, but they should be defined close to
where they are used and inherit logic_error or runtime_error.

I agree that most of these exceptions should not be caught. But i think there
is some value in the class-name of the exception object itself. Again, that's
similar to the errno variable of libc. (what do you want to do if this one
gets set to ENOMEM?)

I can agree to that. It should be specific then, not NumericalException.


Finally, I'll state the obvious that we do not need to discuss. Yes, we
allow throwing exceptions. Yes, all code should satisfy the basic exception
safety guarantee (and all developers are assumed to understand what that
means). No, we do not require the strong gurarantee (but perhaps we
should).

IMHO these guarantees are quite easy to fulfill if you don't use C-style
malloc()+free() memory management. Other options are welcome ;)

Yes, I agree. std::vector saves us all from this particular hell...

Atgeirr

_______________________________________________
Opm mailing list
Opm@opm-project.org
http://www.opm-project.org/mailman/listinfo/opm

Reply via email to