From f6279d3c54a8db14a973f1b76b3cabde7a5648f2 Mon Sep 17 00:00:00 2001 From: David Wells Date: Fri, 27 Apr 2018 18:29:20 -0400 Subject: [PATCH] Avoid using object slicing in AssertNothrow. Previously this function sliced off important information in objects. --- include/deal.II/base/exceptions.h | 38 +++++++++++---- source/base/exceptions.cc | 17 ++----- ...subscriptor.with_threads=off.debug.output} | 21 +++++++-- ...n_subscriptor.with_threads=on.debug.output | 46 +++++++++++++++++++ tests/base/exception_nothrow.debug.output | 12 ----- ...tion_nothrow.with_threads=off.debug.output | 14 ++++++ ...ption_nothrow.with_threads=on.debug.output | 14 ++++++ ...> reference.with_threads=off.debug.output} | 7 ++- .../reference.with_threads=on.debug.output | 30 ++++++++++++ tests/lac/vector_memory.debug.output | 4 +- 10 files changed, 163 insertions(+), 40 deletions(-) rename tests/base/{assign_subscriptor.debug.output => assign_subscriptor.with_threads=off.debug.output} (53%) create mode 100644 tests/base/assign_subscriptor.with_threads=on.debug.output delete mode 100644 tests/base/exception_nothrow.debug.output create mode 100644 tests/base/exception_nothrow.with_threads=off.debug.output create mode 100644 tests/base/exception_nothrow.with_threads=on.debug.output rename tests/base/{reference.debug.output => reference.with_threads=off.debug.output} (66%) create mode 100644 tests/base/reference.with_threads=on.debug.output diff --git a/include/deal.II/base/exceptions.h b/include/deal.II/base/exceptions.h index 3348946340..f5fbdfac88 100644 --- a/include/deal.II/base/exceptions.h +++ b/include/deal.II/base/exceptions.h @@ -19,8 +19,9 @@ #include #include -#include #include +#include +#include #ifdef DEAL_II_WITH_CUDA #include @@ -1039,8 +1040,8 @@ namespace deal_II_exceptions * The actual exception object (the last argument) is typically an unnamed * object created in place; because we modify it, we can't take it by * const reference, and temporaries don't bind to non-const references. - * So take it by value (=copy it) -- the performance implications are - * pretty minimal anyway. + * So take it by value (=copy it) with a templated type to avoid slicing + * -- the performance implications are pretty minimal anyway. * * @ref ExceptionBase */ @@ -1071,18 +1072,37 @@ namespace deal_II_exceptions } } + /** + * Internal function that does the work of issue_error_nothrow. + */ + void + do_issue_error_nothrow(const ExceptionBase &e) noexcept; + /** * Exception generation mechanism in case we must not throw. * * @ref ExceptionBase + * + * @note This function is defined with a template for the same reasons as + * issue_error_noreturn(). */ + template void issue_error_nothrow (ExceptionHandling, - const char *file, - int line, - const char *function, - const char *cond, - const char *exc_name, - ExceptionBase e) noexcept; + const char *file, + int line, + const char *function, + const char *cond, + const char *exc_name, + ExceptionType e) noexcept + { + static_assert(std::is_base_of::value, + "The provided exception must inherit from ExceptionBase."); + // Fill the fields of the exception object + e.set_fields (file, line, function, cond, exc_name); + // avoid moving a bunch of code into the header by dispatching to + // another function: + do_issue_error_nothrow(e); + } #ifdef DEAL_II_WITH_CUDA /** * Return a string given an error code. This is similar to the cudaGetErrorString diff --git a/source/base/exceptions.cc b/source/base/exceptions.cc index cfacef9e3e..4e3873f1d3 100644 --- a/source/base/exceptions.cc +++ b/source/base/exceptions.cc @@ -441,25 +441,16 @@ namespace deal_II_exceptions { namespace internals { - - void issue_error_nothrow (ExceptionHandling, - const char *file, - int line, - const char *function, - const char *cond, - const char *exc_name, - ExceptionBase e) noexcept + void do_issue_error_nothrow (const ExceptionBase &exc) noexcept { - // Fill the fields of the exception object - e.set_fields (file, line, function, cond, exc_name); if (dealii::deal_II_exceptions::abort_on_exception) - internal_abort(e); + internal_abort(exc); else { // We are not allowed to throw, and not allowed to abort. // Just print the exception name to deallog and continue normally: - deallog << "Exception: " << e.get_exc_name() << std::endl; - deallog << e.what() << std::endl; + deallog << "Exception: " << exc.get_exc_name() << std::endl; + deallog << exc.what() << std::endl; } } diff --git a/tests/base/assign_subscriptor.debug.output b/tests/base/assign_subscriptor.with_threads=off.debug.output similarity index 53% rename from tests/base/assign_subscriptor.debug.output rename to tests/base/assign_subscriptor.with_threads=off.debug.output index e2b839e9e0..eb56434e1f 100644 --- a/tests/base/assign_subscriptor.debug.output +++ b/tests/base/assign_subscriptor.with_threads=off.debug.output @@ -7,7 +7,12 @@ An error occurred in file in function The violated condition was: counter == 0 Additional information: - (none) + Object of class N6dealii11SubscriptorE is still used by 1 other objects. + +(Additional information: + from Subscriber v) + +See the entry in the Frequently Asked Questions of deal.II (linked to from http://www.dealii.org/) for a lot more information on what this error means and how to fix programs in which it happens. -------------------------------------------------------- DEAL::Exception: ExcInUse (counter, object_info->name(), infostring) @@ -18,7 +23,12 @@ An error occurred in file in function The violated condition was: counter == 0 Additional information: - (none) + Object of class N6dealii11SubscriptorE is still used by 1 other objects. + +(Additional information: + from Subscriber v) + +See the entry in the Frequently Asked Questions of deal.II (linked to from http://www.dealii.org/) for a lot more information on what this error means and how to fix programs in which it happens. -------------------------------------------------------- DEAL::Exception: ExcInUse (counter, object_info->name(), infostring) @@ -29,6 +39,11 @@ An error occurred in file in function The violated condition was: counter == 0 Additional information: - (none) + Object of class N6dealii11SubscriptorE is still used by 1 other objects. + +(Additional information: + from Subscriber v) + +See the entry in the Frequently Asked Questions of deal.II (linked to from http://www.dealii.org/) for a lot more information on what this error means and how to fix programs in which it happens. -------------------------------------------------------- diff --git a/tests/base/assign_subscriptor.with_threads=on.debug.output b/tests/base/assign_subscriptor.with_threads=on.debug.output new file mode 100644 index 0000000000..38b25642bc --- /dev/null +++ b/tests/base/assign_subscriptor.with_threads=on.debug.output @@ -0,0 +1,46 @@ + +DEAL::Exception: ExcInUse (counter.load(), object_info->name(), infostring) +DEAL:: +-------------------------------------------------------- +An error occurred in file in function + void dealii::Subscriptor::check_no_subscribers() const +The violated condition was: + counter == 0 +Additional information: + Object of class N6dealii11SubscriptorE is still used by 1 other objects. + +(Additional information: ) + +See the entry in the Frequently Asked Questions of deal.II (linked to from http://www.dealii.org/) for a lot more information on what this error means and how to fix programs in which it happens. +-------------------------------------------------------- + +DEAL::Exception: ExcInUse (counter.load(), object_info->name(), infostring) +DEAL:: +-------------------------------------------------------- +An error occurred in file in function + void dealii::Subscriptor::check_no_subscribers() const +The violated condition was: + counter == 0 +Additional information: + Object of class N6dealii11SubscriptorE is still used by 1 other objects. + +(Additional information: ) + +See the entry in the Frequently Asked Questions of deal.II (linked to from http://www.dealii.org/) for a lot more information on what this error means and how to fix programs in which it happens. +-------------------------------------------------------- + +DEAL::Exception: ExcInUse (counter.load(), object_info->name(), infostring) +DEAL:: +-------------------------------------------------------- +An error occurred in file in function + void dealii::Subscriptor::check_no_subscribers() const +The violated condition was: + counter == 0 +Additional information: + Object of class N6dealii11SubscriptorE is still used by 1 other objects. + +(Additional information: ) + +See the entry in the Frequently Asked Questions of deal.II (linked to from http://www.dealii.org/) for a lot more information on what this error means and how to fix programs in which it happens. +-------------------------------------------------------- + diff --git a/tests/base/exception_nothrow.debug.output b/tests/base/exception_nothrow.debug.output deleted file mode 100644 index e1b46e4ebd..0000000000 --- a/tests/base/exception_nothrow.debug.output +++ /dev/null @@ -1,12 +0,0 @@ - -DEAL::Exception: ExcInternalError() -DEAL:: --------------------------------------------------------- -An error occurred in file in function - int main() -The violated condition was: - 1==2 -Additional information: - (none) --------------------------------------------------------- - diff --git a/tests/base/exception_nothrow.with_threads=off.debug.output b/tests/base/exception_nothrow.with_threads=off.debug.output new file mode 100644 index 0000000000..9b745290f7 --- /dev/null +++ b/tests/base/exception_nothrow.with_threads=off.debug.output @@ -0,0 +1,14 @@ + +DEAL::Exception: ExcInternalError() +DEAL:: +-------------------------------------------------------- +An error occurred in file in function + int main() +The violated condition was: + 1==2 +Additional information: + This exception -- which is used in many places in the library -- usually indicates that some condition which the author of the code thought must be satisfied at a certain point in an algorithm, is not fulfilled. An example would be that the first part of an algorithm sorts elements of an array in ascending order, and a second part of the algorithm later encounters an element that is not larger than the previous one. + +There is usually not very much you can do if you encounter such an exception since it indicates an error in deal.II, not in your own program. Try to come up with the smallest possible program that still demonstrates the error and contact the deal.II mailing lists with it to obtain help. +-------------------------------------------------------- + diff --git a/tests/base/exception_nothrow.with_threads=on.debug.output b/tests/base/exception_nothrow.with_threads=on.debug.output new file mode 100644 index 0000000000..9b745290f7 --- /dev/null +++ b/tests/base/exception_nothrow.with_threads=on.debug.output @@ -0,0 +1,14 @@ + +DEAL::Exception: ExcInternalError() +DEAL:: +-------------------------------------------------------- +An error occurred in file in function + int main() +The violated condition was: + 1==2 +Additional information: + This exception -- which is used in many places in the library -- usually indicates that some condition which the author of the code thought must be satisfied at a certain point in an algorithm, is not fulfilled. An example would be that the first part of an algorithm sorts elements of an array in ascending order, and a second part of the algorithm later encounters an element that is not larger than the previous one. + +There is usually not very much you can do if you encounter such an exception since it indicates an error in deal.II, not in your own program. Try to come up with the smallest possible program that still demonstrates the error and contact the deal.II mailing lists with it to obtain help. +-------------------------------------------------------- + diff --git a/tests/base/reference.debug.output b/tests/base/reference.with_threads=off.debug.output similarity index 66% rename from tests/base/reference.debug.output rename to tests/base/reference.with_threads=off.debug.output index a10c6ffb28..07ad086eac 100644 --- a/tests/base/reference.debug.output +++ b/tests/base/reference.with_threads=off.debug.output @@ -18,7 +18,12 @@ An error occurred in file in function The violated condition was: counter == 0 Additional information: - (none) + Object of class 4Test is still used by 1 other objects. + +(Additional information: + from Subscriber Test R) + +See the entry in the Frequently Asked Questions of deal.II (linked to from http://www.dealii.org/) for a lot more information on what this error means and how to fix programs in which it happens. -------------------------------------------------------- DEAL::Destruct C diff --git a/tests/base/reference.with_threads=on.debug.output b/tests/base/reference.with_threads=on.debug.output new file mode 100644 index 0000000000..0ef6086057 --- /dev/null +++ b/tests/base/reference.with_threads=on.debug.output @@ -0,0 +1,30 @@ + +DEAL::Construct A +DEAL::Construct B +DEAL::a mutable +DEAL::b const +DEAL::r mutable +DEAL::s const +DEAL::t mutable +DEAL::u const +DEAL::Construct C +DEAL::Construct D +DEAL::Destruct D +DEAL::Exception: ExcInUse (counter.load(), object_info->name(), infostring) +DEAL:: +-------------------------------------------------------- +An error occurred in file in function + void dealii::Subscriptor::check_no_subscribers() const +The violated condition was: + counter == 0 +Additional information: + Object of class 4Test is still used by 1 other objects. + +(Additional information: ) + +See the entry in the Frequently Asked Questions of deal.II (linked to from http://www.dealii.org/) for a lot more information on what this error means and how to fix programs in which it happens. +-------------------------------------------------------- + +DEAL::Destruct C +DEAL::Destruct B +DEAL::Destruct A diff --git a/tests/lac/vector_memory.debug.output b/tests/lac/vector_memory.debug.output index 9024914435..7debc7bb04 100644 --- a/tests/lac/vector_memory.debug.output +++ b/tests/lac/vector_memory.debug.output @@ -9,7 +9,7 @@ An error occurred in file in function The violated condition was: current_alloc == 0 Additional information: - (none) + Destroying memory handler while 1 objects are still allocated. -------------------------------------------------------- DEAL::Exception: StandardExceptions::ExcMemoryLeak(current_alloc) @@ -20,6 +20,6 @@ An error occurred in file in function The violated condition was: current_alloc == 0 Additional information: - (none) + Destroying memory handler while 1 objects are still allocated. -------------------------------------------------------- -- 2.39.5