From 2960ba939f4e1fa19686ce1c453648292b46bb7a Mon Sep 17 00:00:00 2001 From: maier Date: Tue, 16 Apr 2013 14:42:49 +0000 Subject: [PATCH] Refactor ExceptionBase as well as the Assert and AssertThrow macros git-svn-id: https://svn.dealii.org/trunk@29300 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/include/deal.II/base/exceptions.h | 381 +++++++++------------- deal.II/source/base/exceptions.cc | 251 +++++--------- 2 files changed, 239 insertions(+), 393 deletions(-) diff --git a/deal.II/include/deal.II/base/exceptions.h b/deal.II/include/deal.II/base/exceptions.h index 613252055e..e850c4e51e 100644 --- a/deal.II/include/deal.II/base/exceptions.h +++ b/deal.II/include/deal.II/base/exceptions.h @@ -19,7 +19,7 @@ #include -#include +#include #include #include @@ -36,9 +36,9 @@ DEAL_II_NAMESPACE_OPEN * what can be done with classes derived from it. * * @ingroup Exceptions - * @author Wolfgang Bangerth, 1997, extensions 1998 + * @author Wolfgang Bangerth, 1997, 1998, Matthias Maier, 2013 */ -class ExceptionBase : public std::exception +class ExceptionBase : public std::runtime_error { public: /** @@ -46,27 +46,13 @@ public: */ ExceptionBase (); - /** - * The constructor takes the file in which the error happened, - * the line and the violated condition as well as the name of the - * exception class as a char* as arguments. - */ - ExceptionBase (const char *file, - int line, - const char *function, - const char *cond, - const char *exc_name); - /** * Copy constructor. */ ExceptionBase (const ExceptionBase &exc); /** - * Destructor. Empty, but needed for the sake of exception - * specification, since the base class has this exception - * specification and the automatically generated destructor would - * have a different one due to member objects. + * Destructor. */ virtual ~ExceptionBase () throw(); @@ -81,6 +67,11 @@ public: const char *cond, const char *exc_name); + /** + * Get exception name. + */ + const char * get_exc_name() const; + /** * Print out the general part of the error information. */ @@ -92,18 +83,6 @@ public: */ virtual void print_info (std::ostream &out) const; - - /** - * Function derived from the base class which allows to pass - * information like the line and name of the file where the exception - * occurred as well as user information. - * - * This function is mainly used when using exceptions declared by the - * DeclException* macros with the throw mechanism or - * the AssertThrow macro. - */ - virtual const char *what () const throw (); - /** * Print a stacktrace, if one has been recorded previously, to the * given stream. @@ -112,7 +91,7 @@ public: protected: /** - * Name of the file this exception happen in. + * Name of the file this exception happens in. */ const char *file; @@ -151,9 +130,8 @@ protected: - /** - * In this namespace functions in connection with the Assert and + * In this namespace, functions in connection with the Assert and * AssertThrow mechanism are declared. * * @ingroup Exceptions @@ -172,11 +150,11 @@ namespace deal_II_exceptions * which the program runs, so that one can see in which instance of the * program the exception occured. * - * The string pointed to by the argument is copied, so needs not be + * The string pointed to by the argument is copied, so doesn't need to be * stored after the call to this function. * - * Previously set additional output is replaced by the argument given - * to this function. + * Previously set additional output is replaced by the argument given to + * this function. */ void set_additional_assert_output (const char *const p); @@ -191,16 +169,15 @@ namespace deal_II_exceptions void suppress_stacktrace_in_exceptions (); /** - * Calling this function switches off the use of std::abort() when an - * exception is created using the Assert() macro. Instead, the Exception - * will be thrown using 'throw', so it can be caught if desired. - * Generally, you want - * to abort the execution of a program when Assert() is called, but it - * needs to be switched off if you want to log all exceptions created, - * or if you want to test if an assertion is working correctly. This is - * done for example in regression tests. Please note that some fatal - * errors will still call abort(), e.g. when an exception is caught - * during exception handling. + * Calling this function switches off the use of std::abort() + * when an exception is created using the Assert() macro. Instead, the + * Exception will be thrown using 'throw', so it can be caught if + * desired. Generally, you want to abort the execution of a program when + * Assert() is called, but it needs to be switched off if you want to log + * all exceptions created, or if you want to test if an assertion is + * working correctly. This is done for example in regression tests. + * Please note that some fatal errors will still call abort(), e.g. when + * an exception is caught during exception handling. */ void disable_abort_on_exception (); @@ -216,27 +193,21 @@ namespace deal_II_exceptions { /** - * This routine does the main work for the exception generation - * mechanism used in the Assert macro. - * - * @ref ExceptionBase + * Conditionally abort the program. Depending on whether + * disable_abort_on_exception was called, this function either aborts + * the program flow by printing an error message and calling + * std::abort(), or throws @p exc instead. */ - void issue_error_assert (const char *file, - int line, - const char *function, - const char *cond, - const char *exc_name, - ExceptionBase &e); - + void abort (const ExceptionBase &exc); /** * This routine does the main work for the exception generation - * mechanism used in the AssertThrow macro. + * mechanism used in the Assert macro. * * @ref ExceptionBase */ template - void issue_error_throw (const char *file, + void issue_error_abort (const char *file, int line, const char *function, const char *cond, @@ -245,68 +216,57 @@ namespace deal_II_exceptions { // Fill the fields of the exception object e.set_fields (file, line, function, cond, exc_name); - throw e; - } + dealii::deal_II_exceptions::internals::abort(e); + } /** - * Relay exceptions from the Assert macro to the - * __IssueError_Assert function. Used to convert the last - * argument from arbitrary type to ExceptionBase which is not - * possible inside the Assert macro due to syntactical - * difficulties in connection with the way we use the macro and the - * declaration of the exception classes. + * This routine does the main work for the exception generation + * mechanism used in the AssertThrow macro. * * @ref ExceptionBase */ template - inline - void issue_error_assert_1 (const char *file, - int line, - const char *function, - const char *cond, - const char *exc_name, - exc e) + void issue_error (const char *file, + int line, + const char *function, + const char *cond, + const char *exc_name, + exc e) { - issue_error_assert (file,line,function,cond,exc_name,e); + // Fill the fields of the exception object + e.set_fields (file, line, function, cond, exc_name); + throw e; } + } /*namespace internals*/ - /** - * Abort the program. This function is used so that we need not - * include cstdlib into this file since it is included into all - * other files of the library and we would like to keep its include - * list as short as possible. - */ - void abort (); - - } -} +} /*namespace deal_II_exceptions*/ -#ifdef DEBUG /** * This is the main routine in the exception mechanism for debug mode * error checking. It asserts that a certain condition is fulfilled, * otherwise issues an error and aborts the program. * - * See the ExceptionBase class for more information. + * See the ExceptionBase class for more information. * * @ingroup Exceptions - * @author Wolfgang Bangerth, November 1997, extensions 1998 + * @author Wolfgang Bangerth, 1997, 1998, Matthias Maier, 2013 */ -#define Assert(cond, exc) \ - { \ - if (!(cond)) \ - ::dealii::deal_II_exceptions::internals:: \ - issue_error_assert_1 (__FILE__, \ - __LINE__, \ - __PRETTY_FUNCTION__, #cond, #exc, exc); \ +#ifdef DEBUG +#define Assert(cond, exc) \ + { \ + if (!(cond)) \ + ::dealii::deal_II_exceptions::internals:: \ + issue_error_abort (__FILE__, \ + __LINE__, \ + __PRETTY_FUNCTION__, #cond, #exc, exc); \ } #else -#define Assert(cond, exc) \ +#define Assert(cond, exc) \ { } #endif @@ -317,49 +277,32 @@ namespace deal_II_exceptions * mode error checking. It assert that a certain condition is * fulfilled, otherwise issues an error and aborts the program. * - * On some systems (we only know of DEC Alpha systems running under - * OSF1 or Linux), the compiler fails to compile the AssertThrow - * macro properly, yielding an internal compiler error. We detect this - * at configure time. For these cases, the AssertThrow macro aborts - * the program if the assertion is not satisfied. This, however, - * happens in debug and optimized mode likewise. Note that in these - * cases, the meaning of a program changes. In particular, one cannot - * catch exceptions thrown by AssertThrow, but we did not find - * another way to work around this compiler bug. - * * See the ExceptionBase class for more information. * * @ref ExceptionBase * @ingroup Exceptions - * @author Wolfgang Bangerth, November 1997, extensions 1998 + * @author Wolfgang Bangerth, 1997, 1998, Matthias Maier, 2013 */ -#ifndef DISABLE_ASSERT_THROW -# ifndef HAVE_BUILTIN_EXPECT -# define AssertThrow(cond, exc) \ - { \ - if (!(cond)) \ - ::dealii::deal_II_exceptions::internals:: \ - issue_error_throw (__FILE__, \ - __LINE__, \ - __PRETTY_FUNCTION__, #cond, #exc, exc); \ - } -# else /*ifndef HAVE_BUILTIN_EXPECT*/ -# define AssertThrow(cond, exc) \ - { \ - if (__builtin_expect(!(cond), false)) \ - ::dealii::deal_II_exceptions::internals:: \ - issue_error_throw (__FILE__, \ - __LINE__, \ - __PRETTY_FUNCTION__, #cond, #exc, exc); \ +#ifdef HAVE_BUILTIN_EXPECT +#define AssertThrow(cond, exc) \ + { \ + if (__builtin_expect(!(cond), false)) \ + ::dealii::deal_II_exceptions::internals:: \ + issue_error (__FILE__, \ + __LINE__, \ + __PRETTY_FUNCTION__, #cond, #exc, exc); \ } -# endif /*ifndef HAVE_BUILTIN_EXPECT*/ -#else -# define AssertThrow(cond, exc) \ - { \ - if (!(cond)) \ - ::dealii::deal_II_exceptions::internals::abort (); \ + +#else /*ifdef HAVE_BUILTIN_EXPECT*/ +#define AssertThrow(cond, exc) \ + { \ + if (!(cond)) \ + ::dealii::deal_II_exceptions::internals:: \ + issue_error (__FILE__, \ + __LINE__, \ + __PRETTY_FUNCTION__, #cond, #exc, exc); \ } -#endif +#endif /*ifdef HAVE_BUILTIN_EXPECT*/ @@ -371,7 +314,7 @@ namespace deal_II_exceptions * @author Wolfgang Bangerth, November 1997 * @ingroup Exceptions */ -#define DeclException0(Exception0) \ +#define DeclException0(Exception0) \ class Exception0 : public dealii::ExceptionBase {} @@ -381,16 +324,16 @@ namespace deal_II_exceptions * * @ingroup Exceptions */ -#define DeclException1(Exception1, type1, outsequence) \ - class Exception1 : public dealii::ExceptionBase { \ - public: \ - Exception1 (const type1 a1) : arg1 (a1) {} \ - virtual ~Exception1 () throw () {} \ - virtual void print_info (std::ostream &out) const { \ - out outsequence << std::endl; \ - } \ - private: \ - const type1 arg1; \ +#define DeclException1(Exception1, type1, outsequence) \ + class Exception1 : public dealii::ExceptionBase { \ + public: \ + Exception1 (const type1 a1) : arg1 (a1) {} \ + virtual ~Exception1 () throw () {} \ + virtual void print_info (std::ostream &out) const { \ + out outsequence << std::endl; \ + } \ + private: \ + const type1 arg1; \ } @@ -400,18 +343,18 @@ namespace deal_II_exceptions * * @ingroup Exceptions */ -#define DeclException2(Exception2, type1, type2, outsequence) \ - class Exception2 : public dealii::ExceptionBase { \ - public: \ - Exception2 (const type1 a1, const type2 a2) : \ - arg1 (a1), arg2(a2) {} \ - virtual ~Exception2 () throw () {} \ - virtual void print_info (std::ostream &out) const { \ - out outsequence << std::endl; \ - } \ - private: \ - const type1 arg1; \ - const type2 arg2; \ +#define DeclException2(Exception2, type1, type2, outsequence) \ + class Exception2 : public dealii::ExceptionBase { \ + public: \ + Exception2 (const type1 a1, const type2 a2) : \ + arg1 (a1), arg2(a2) {} \ + virtual ~Exception2 () throw () {} \ + virtual void print_info (std::ostream &out) const { \ + out outsequence << std::endl; \ + } \ + private: \ + const type1 arg1; \ + const type2 arg2; \ } @@ -421,19 +364,19 @@ namespace deal_II_exceptions * * @ingroup Exceptions */ -#define DeclException3(Exception3, type1, type2, type3, outsequence) \ - class Exception3 : public dealii::ExceptionBase { \ - public: \ - Exception3 (const type1 a1, const type2 a2, const type3 a3) : \ - arg1 (a1), arg2(a2), arg3(a3) {} \ - virtual ~Exception3 () throw () {} \ - virtual void print_info (std::ostream &out) const { \ - out outsequence << std::endl; \ - } \ - private: \ - const type1 arg1; \ - const type2 arg2; \ - const type3 arg3; \ +#define DeclException3(Exception3, type1, type2, type3, outsequence) \ + class Exception3 : public dealii::ExceptionBase { \ + public: \ + Exception3 (const type1 a1, const type2 a2, const type3 a3) : \ + arg1 (a1), arg2(a2), arg3(a3) {} \ + virtual ~Exception3 () throw () {} \ + virtual void print_info (std::ostream &out) const { \ + out outsequence << std::endl; \ + } \ + private: \ + const type1 arg1; \ + const type2 arg2; \ + const type3 arg3; \ } @@ -444,20 +387,20 @@ namespace deal_II_exceptions * @ingroup Exceptions */ #define DeclException4(Exception4, type1, type2, type3, type4, outsequence) \ - class Exception4 : public dealii::ExceptionBase { \ - public: \ - Exception4 (const type1 a1, const type2 a2, \ - const type3 a3, const type4 a4) : \ - arg1 (a1), arg2(a2), arg3(a3), arg4(a4) {} \ - virtual ~Exception4 () throw () {} \ - virtual void print_info (std::ostream &out) const { \ - out outsequence << std::endl; \ - } \ - private: \ - const type1 arg1; \ - const type2 arg2; \ - const type3 arg3; \ - const type4 arg4; \ + class Exception4 : public dealii::ExceptionBase { \ + public: \ + Exception4 (const type1 a1, const type2 a2, \ + const type3 a3, const type4 a4) : \ + arg1 (a1), arg2(a2), arg3(a3), arg4(a4) {} \ + virtual ~Exception4 () throw () {} \ + virtual void print_info (std::ostream &out) const { \ + out outsequence << std::endl; \ + } \ + private: \ + const type1 arg1; \ + const type2 arg2; \ + const type3 arg3; \ + const type4 arg4; \ } @@ -468,25 +411,26 @@ namespace deal_II_exceptions * @ingroup Exceptions */ #define DeclException5(Exception5, type1, type2, type3, type4, type5, outsequence) \ - class Exception5 : public dealii::ExceptionBase { \ - public: \ - Exception5 (const type1 a1, const type2 a2, const type3 a3, \ - const type4 a4, const type5 a5) : \ - arg1 (a1), arg2(a2), arg3(a3), arg4(a4), arg5(a5) {} \ - virtual ~Exception5 () throw () {} \ - virtual void print_info (std::ostream &out) const { \ - out outsequence << std::endl; \ - } \ - private: \ - const type1 arg1; \ - const type2 arg2; \ - const type3 arg3; \ - const type4 arg4; \ - const type5 arg5; \ + class Exception5 : public dealii::ExceptionBase { \ + public: \ + Exception5 (const type1 a1, const type2 a2, const type3 a3, \ + const type4 a4, const type5 a5) : \ + arg1 (a1), arg2(a2), arg3(a3), arg4(a4), arg5(a5) {} \ + virtual ~Exception5 () throw () {} \ + virtual void print_info (std::ostream &out) const { \ + out outsequence << std::endl; \ + } \ + private: \ + const type1 arg1; \ + const type2 arg2; \ + const type3 arg3; \ + const type4 arg4; \ + const type5 arg5; \ } #else /*ifndef DOXYGEN*/ +// Dummy definitions for doxygen: /** * Declare an exception class derived from ExceptionBase without parameters. @@ -494,7 +438,7 @@ namespace deal_II_exceptions * @author Wolfgang Bangerth, November 1997 * @ingroup Exceptions */ -#define DeclException0(Exception0) \ +#define DeclException0(Exception0) \ static dealii::ExceptionBase& Exception0 () @@ -504,33 +448,33 @@ namespace deal_II_exceptions * * @ingroup Exceptions */ -#define DeclException1(Exception1, type1, outsequence) \ +#define DeclException1(Exception1, type1, outsequence) \ static dealii::ExceptionBase& Exception1 (type1 arg1) throw (errortext outsequence) /** - * Declare an exception class derived from ExceptionBase with - * two additional parameters. + * Declare an exception class derived from ExceptionBase with two + * additional parameters. * * @ingroup Exceptions */ -#define DeclException2(Exception2, type1, type2, outsequence) \ +#define DeclException2(Exception2, type1, type2, outsequence) \ static dealii::ExceptionBase& Exception2 (type1 arg1, type2 arg2) throw (errortext outsequence) /** - * Declare an exception class derived from ExceptionBase with - * three additional parameters. + * Declare an exception class derived from ExceptionBase with three + * additional parameters. * * @ingroup Exceptions */ -#define DeclException3(Exception3, type1, type2, type3, outsequence) \ +#define DeclException3(Exception3, type1, type2, type3, outsequence) \ static dealii::ExceptionBase& Exception3 (type1 arg1, type2 arg2, type3 arg3) throw (errortext outsequence) /** - * Declare an exception class derived from ExceptionBase with - * four additional parameters. + * Declare an exception class derived from ExceptionBase with four + * additional parameters. * * @ingroup Exceptions */ @@ -539,8 +483,8 @@ namespace deal_II_exceptions /** - * Declare an exception class derived from ExceptionBase with - * five additional parameters. + * Declare an exception class derived from ExceptionBase with five + * additional parameters. * * @ingroup Exceptions */ @@ -571,10 +515,9 @@ namespace StandardExceptions /** * Exception denoting a division by zero. * - * @note Unfortunately, automatic detection of division by zero - * is very hardware dependent and requires severe hacking on some - * architectures. - * Therefore, this exception is only raised if the test s performed + * @note Unfortunately, automatic detection of division by zero is very + * hardware dependent and requires severe hacking on some architectures. + * Therefore, this exception is only raised if the test is performed * explicitly. */ DeclException0 (ExcDivideByZero); @@ -582,9 +525,9 @@ namespace StandardExceptions /** * Exception raised if a number is not finite. * - * This exception should be used to catch infinite or not a number results - * of arithmetic operations that do not result from a division by zero - * (use ExcDivideByZero for those). + * This exception should be used to catch infinite or not a number + * results of arithmetic operations that do not result from a division by + * zero (use ExcDivideByZero for those). */ DeclException0 (ExcNumberNotFinite); @@ -770,10 +713,10 @@ namespace StandardExceptions /** * This exception works around a design flaw in the - * DeclException0 macro: exceptions desclared through + * DeclException0 macro: exceptions declared through * DeclException0 do not allow one to specify a message that is displayed - * when the exception is raised, as opposed to the other exceptions - * which allow to show a text along with the given parameters. + * when the exception is raised, as opposed to the other exceptions which + * allow to show a text along with the given parameters. * * When throwing this exception, you can give a message as a * std::string as argument to the exception that is then diff --git a/deal.II/source/base/exceptions.cc b/deal.II/source/base/exceptions.cc index f6e97c86a9..f7f5582a3b 100644 --- a/deal.II/source/base/exceptions.cc +++ b/deal.II/source/base/exceptions.cc @@ -40,8 +40,6 @@ namespace deal_II_exceptions additional_assert_output = p; } - - bool show_stacktrace = true; void suppress_stacktrace_in_exceptions () @@ -49,30 +47,25 @@ namespace deal_II_exceptions show_stacktrace = false; } - bool abort_on_exception = true; void disable_abort_on_exception () { abort_on_exception = false; } + } ExceptionBase::ExceptionBase () : - file(""), line(0), function(""), cond(""), exc(""), - stacktrace (0), - n_stacktrace_frames (0) -{} - - - -ExceptionBase::ExceptionBase (const char *f, const int l, const char *func, - const char *c, const char *e) - : - file(f), line(l), function(func), cond(c), exc(e), + std::runtime_error(""), + file(""), + line(0), + function(""), + cond(""), + exc(""), stacktrace (0), n_stacktrace_frames (0) {} @@ -81,11 +74,13 @@ ExceptionBase::ExceptionBase (const char *f, const int l, const char *func, ExceptionBase::ExceptionBase (const ExceptionBase &exc) : - std::exception (exc), - file(exc.file), line(exc.line), - function(exc.function), cond(exc.cond), exc(exc.exc), - // don't copy stacktrace to avoid double de-allocation problem - stacktrace (0), + std::runtime_error (exc), + file(exc.file), + line(exc.line), + function(exc.function), + cond(exc.cond), + exc(exc.exc), + stacktrace (0), // don't copy stacktrace to avoid double de-allocation problem n_stacktrace_frames (0) {} @@ -103,7 +98,7 @@ ExceptionBase::~ExceptionBase () throw () void ExceptionBase::set_fields (const char *f, - const int l, + const int l, const char *func, const char *c, const char *e) @@ -120,6 +115,60 @@ void ExceptionBase::set_fields (const char *f, n_stacktrace_frames = backtrace(array, 25); stacktrace = backtrace_symbols(array, n_stacktrace_frames); #endif + + // build up a string with the error message... + + std::ostringstream converter; + + converter << std::endl + << "--------------------------------------------------------" + << std::endl; + // print out general data + print_exc_data (converter); + // print out exception specific data + print_info (converter); + print_stack_trace (converter); + + if (!deal_II_exceptions::additional_assert_output.empty()) + converter << "--------------------------------------------------------" + << std::endl + << deal_II_exceptions::additional_assert_output + << std::endl; + + converter << "--------------------------------------------------------" + << std::endl; + + // ... and setup the final error message with it: + static_cast(*this) = std::runtime_error(converter.str()); +} + + + +const char * ExceptionBase::get_exc_name () const +{ + return exc; +} + + + +void ExceptionBase::print_exc_data (std::ostream &out) const +{ + out << "An error occurred in line <" << line + << "> of file <" << file + << "> in function" << std::endl + << " " << function << std::endl + << "The violated condition was: "<< std::endl + << " " << cond << std::endl + << "The name and call sequence of the exception was:" << std::endl + << " " << exc << std::endl + << "Additional Information: " << std::endl; +} + + + +void ExceptionBase::print_info (std::ostream &out) const +{ + out << "(none)" << std::endl; } @@ -132,7 +181,6 @@ void ExceptionBase::print_stack_trace (std::ostream &out) const if (deal_II_exceptions::show_stacktrace == false) return; - // if there is a stackframe stored, print it out << std::endl; out << "Stacktrace:" << std::endl @@ -223,179 +271,34 @@ void ExceptionBase::print_stack_trace (std::ostream &out) const } -void ExceptionBase::print_exc_data (std::ostream &out) const -{ - out << "An error occurred in line <" << line - << "> of file <" << file - << "> in function" << std::endl - << " " << function << std::endl - << "The violated condition was: "<< std::endl - << " " << cond << std::endl - << "The name and call sequence of the exception was:" << std::endl - << " " << exc << std::endl - << "Additional Information: " << std::endl; - // Additionally, leave a trace in deallog if we do not stop here - if (deal_II_exceptions::abort_on_exception == false) - deallog << exc << std::endl; -} - - -void ExceptionBase::print_info (std::ostream &out) const -{ - out << "(none)" << std::endl; -} - - -// TODO ! -const char *ExceptionBase::what () const throw () -{ - // if we say that this function does not throw exceptions, we better make - // sure it does not - try - { - // have a place where to store the description of the exception as a - // char * - // - // this thing obviously is not multi-threading safe, but we don't - // care about that for now - // - // we need to make this object static, since we want to return the - // data stored in it and therefore need a lifetime which is longer - // than the execution time of this function - static std::string description; - // convert the messages printed by the exceptions into a std::string - std::ostringstream converter; - - converter << "--------------------------------------------------------" - << std::endl; - // put general info into the std::string - print_exc_data (converter); - // put in exception specific data - print_info (converter); - - print_stack_trace (converter); - - converter << "--------------------------------------------------------" - << std::endl; - - description = converter.str(); - - return description.c_str(); - } - catch (std::exception &exc) - { - std::cerr << "*** Exception encountered in exception handling routines ***" - << std::endl - << "*** Message is " << std::endl - << exc.what () << std::endl - << "*** Aborting! ***" << std::endl; - - std::abort (); - } - catch (...) - { - std::cerr << "*** Exception encountered in exception handling routines ***" - << std::endl - << "*** Aborting! ***" << std::endl; - - std::abort (); - } - return 0; -} - - namespace deal_II_exceptions { namespace internals { - /** - * Number of exceptions dealt with so far. Zero at program start. - * Messages are only displayed if the value is zero. - */ - unsigned int n_treated_exceptions; - ExceptionBase *last_exception; - - - void issue_error_assert (const char *file, - int line, - const char *function, - const char *cond, - const char *exc_name, - ExceptionBase &e) + void abort (const ExceptionBase &exc) { - // fill the fields of the exception object - e.set_fields (file, line, function, cond, exc_name); - - // if no other exception has been displayed before, show this one - if (n_treated_exceptions == 0) + if(dealii::deal_II_exceptions::abort_on_exception) { - std::cerr << "--------------------------------------------------------" - << std::endl; - // print out general data - e.print_exc_data (std::cerr); - // print out exception specific data - e.print_info (std::cerr); - e.print_stack_trace (std::cerr); - std::cerr << "--------------------------------------------------------" - << std::endl; - - // if there is more to say, do so - if (!additional_assert_output.empty()) - std::cerr << additional_assert_output << std::endl; + std::cerr << exc.what() << std::endl; + std::abort(); } else { - // if this is the first follow-up message, display a message that - // further exceptions are suppressed - if (n_treated_exceptions == 1) - std::cerr << "******** More assertions fail but messages are suppressed! ********" - << std::endl; - }; - - // increase number of treated exceptions by one - n_treated_exceptions++; - last_exception = &e; - - - // abort the program now since something has gone horribly wrong. - // however, there is one case where we do not want to do that, namely - // when another exception, possibly thrown by AssertThrow is active, - // since in that case we will not come to see the original exception. - // in that case indicate that the program is not aborted due to this - // reason. - if (std::uncaught_exception() == true) - { - // only display message once - if (n_treated_exceptions <= 1) - std::cerr << "******** Program is not aborted since another exception is active! ********" - << std::endl; - } - else if (deal_II_exceptions::abort_on_exception == true) - std::abort (); - else - { - --n_treated_exceptions; - throw e; + throw exc; } } + } /*namespace internals*/ +} /*namespace deal_II_exceptions*/ - void abort () - { - if (deal_II_exceptions::abort_on_exception == true) - std::abort (); - } - - } - -} DEAL_II_NAMESPACE_CLOSE + // Newer versions of gcc have a very nice feature: you can set a verbose // terminate handler, that not only aborts a program when an exception is // thrown and not caught somewhere, but before aborting it prints that an -- 2.39.5