]> https://gitweb.dealii.org/ - dealii-svn.git/commitdiff
Cleanup ExceptionBase: Inherit from std::exception and do the c_string handling direc...
authormaier <maier@0785d39b-7218-0410-832d-ea1e28bc413d>
Wed, 20 Nov 2013 10:31:09 +0000 (10:31 +0000)
committermaier <maier@0785d39b-7218-0410-832d-ea1e28bc413d>
Wed, 20 Nov 2013 10:31:09 +0000 (10:31 +0000)
git-svn-id: https://svn.dealii.org/trunk@31723 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/include/deal.II/base/exceptions.h
deal.II/source/base/exceptions.cc

index 0f5f4c393d45dac39ebc63d1d35421659f02d3d9..8c5efbd8593d5701d1a884d48230831aa77ad68e 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <deal.II/base/config.h>
 
-#include <stdexcept>
+#include <exception>
 #include <string>
 #include <ostream>
 
@@ -43,7 +43,7 @@ DEAL_II_NAMESPACE_OPEN
  * @ingroup Exceptions
  * @author Wolfgang Bangerth, 1997, 1998, Matthias Maier, 2013
  */
-class ExceptionBase : public std::runtime_error
+class ExceptionBase : public std::exception
 {
 public:
   /**
@@ -147,11 +147,15 @@ protected:
 
 private:
   /**
-   * Internal function that generates the c_string that gets printed by
-   * exception::what(). Called by the ExceptionBase constructor and
-   * set_fields.
+   * Internal function that generates the c_string. Called by what().
    */
   void generate_message() const;
+
+  /**
+   * A pointer to the c_string that will be printed by what(). It is
+   * populated by generate_message()
+   */
+  mutable char* what_str;
 };
 
 
index 590f1ce1f68cd441dffd63d73359064640eaf0f3..22278be947e77a76d2f2b3f411402f81ff9f9709 100644 (file)
@@ -62,31 +62,28 @@ namespace deal_II_exceptions
 
 ExceptionBase::ExceptionBase ()
   :
-  std::runtime_error(""),
   file(""),
   line(0),
   function(""),
   cond(""),
   exc(""),
   stacktrace (0),
-  n_stacktrace_frames (0)
-{
-  // Construct a minimalistic error message:
-  generate_message();
-}
+  n_stacktrace_frames (0),
+  what_str(0)
+{}
 
 
 
 ExceptionBase::ExceptionBase (const ExceptionBase &exc)
   :
-  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)
+  n_stacktrace_frames (0),
+  what_str(0) // don't copy the error message, it gets generated dynamically by what()
 {}
 
 
@@ -98,6 +95,11 @@ ExceptionBase::~ExceptionBase () throw ()
       free (stacktrace);
       stacktrace = 0;
     }
+  if (what_str != 0)
+    {
+      delete[] what_str;
+      what_str = 0;
+    }
 }
 
 
@@ -128,26 +130,24 @@ void ExceptionBase::set_fields (const char *f,
 #ifdef HAVE_GLIBC_STACKTRACE
   n_stacktrace_frames = backtrace(raw_stacktrace, 25);
 #endif
-
-  // set the message to the empty string so that what() will compute
-  // a new error message with the new information.
-  std::runtime_error * base = static_cast<std::runtime_error *>(this);
-  *base = std::runtime_error("");
 }
 
 const char* ExceptionBase::what() const throw()
 {
-  // We override the what() function to be able to look up the symbols
-  // of the stack trace.
-  if (std::runtime_error::what()[0]=='\0')
+  // If no error c_string was generated so far, do it now:
+  if (what_str == 0)
     {
 #ifdef HAVE_GLIBC_STACKTRACE
+      // We have deferred the symbol lookup to this point to avoid costly
+      // runtime penalties due to linkage of external libraries by
+      // backtrace_symbols.
       stacktrace = backtrace_symbols(raw_stacktrace, n_stacktrace_frames);
 #endif
 
       generate_message();
     }
-  return std::runtime_error::what();
+
+  return what_str;
 }
 
 
@@ -281,35 +281,43 @@ void ExceptionBase::print_stack_trace (std::ostream &out) const
 
 void ExceptionBase::generate_message () const
 {
-  // build up a string with the error message...
+  // build up a c_string with the error message.
+  // Guard this procedure with a try block, we shall not throw at this
+  // place...
+  try
+    {
+      std::ostringstream converter;
 
-  std::ostringstream converter;
+      converter << std::endl
+                << "--------------------------------------------------------"
+                << std::endl;
 
-  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);
 
-  // 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;
+        }
 
-  if (!deal_II_exceptions::additional_assert_output.empty())
-    {
       converter << "--------------------------------------------------------"
-                << std::endl
-                << deal_II_exceptions::additional_assert_output
                 << std::endl;
-    }
 
-  converter << "--------------------------------------------------------"
-            << std::endl;
-
-  // ... and set up std::runtime_error with it. We need to do a const
-  // cast so we can change the what message even though our method is const.
-  const std::runtime_error * base = static_cast<const std::runtime_error *>(this);
-  const_cast<std::runtime_error &>(*base) = std::runtime_error(converter.str());
+      if (what_str != 0)
+        delete[] what_str;
+      what_str = new char[converter.str().size()+1]; // beware of the terminating \0 character
+      strcpy(what_str, converter.str().c_str());
+    }
+  catch (...)
+    {
+      // On error, resume next. There is nothing better we can do...
+    }
 }
 
 

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.