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