From: heltai Date: Sun, 12 Apr 2009 09:00:53 +0000 (+0000) Subject: Made Vector::reinit virtual, to avoid memory corruption in VectorView X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd36f15d347ef5cea2833b7c2cf3c93eb7eae800;p=dealii-svn.git Made Vector::reinit virtual, to avoid memory corruption in VectorView git-svn-id: https://svn.dealii.org/trunk@18598 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/lac/include/lac/vector.h b/deal.II/lac/include/lac/vector.h index 3bac18a7e0..cc6aa2ddcc 100644 --- a/deal.II/lac/include/lac/vector.h +++ b/deal.II/lac/include/lac/vector.h @@ -308,9 +308,14 @@ class Vector : public Subscriptor * filled by zeros. Otherwise, the * elements are left an unspecified * state. + * + * This function is virtual in + * order to allow for derived + * classes to handle memory + * separately. */ - void reinit (const unsigned int N, - const bool fast=false); + virtual void reinit (const unsigned int N, + const bool fast=false); /** * Change the dimension to that of the @@ -347,8 +352,13 @@ class Vector : public Subscriptor * swap(u,v) that simply calls * u.swap(v), again in analogy * to standard functions. - */ - void swap (Vector &v); + * + * This function is virtual in + * order to allow for derived + * classes to handle memory + * separately. + */ + virtual void swap (Vector &v); /** * Set all components of the vector to @@ -1179,6 +1189,21 @@ Vector::compress () const {} +// Moved from vector.templates.h as an inline function by Luca Heltai +// on 2009/04/12 to prevent strange compiling errors, after making +// swap virtual. +template +inline +void +Vector::swap (Vector &v) +{ + std::swap (vec_size, v.vec_size); + std::swap (max_vec_size, v.max_vec_size); + std::swap (val, v.val); +} + + + /*! @addtogroup Vectors *@{ diff --git a/deal.II/lac/include/lac/vector.templates.h b/deal.II/lac/include/lac/vector.templates.h index c6aad63827..20555a62b9 100644 --- a/deal.II/lac/include/lac/vector.templates.h +++ b/deal.II/lac/include/lac/vector.templates.h @@ -239,16 +239,17 @@ void Vector::reinit (const Vector& v, reinit (v.size(), fast); } - - -template -void -Vector::swap (Vector &v) -{ - std::swap (vec_size, v.vec_size); - std::swap (max_vec_size, v.max_vec_size); - std::swap (val, v.val); -} +// Moved to vector.h as an inline function by Luca Heltai on +// 2009/04/12 to prevent strange compiling errors, after making swap +// virtual. +// template +// void +// Vector::swap (Vector &v) +// { +// std::swap (vec_size, v.vec_size); +// std::swap (max_vec_size, v.max_vec_size); +// std::swap (val, v.val); +// } diff --git a/deal.II/lac/include/lac/vector_view.h b/deal.II/lac/include/lac/vector_view.h index 20038ec37f..28d6839fae 100644 --- a/deal.II/lac/include/lac/vector_view.h +++ b/deal.II/lac/include/lac/vector_view.h @@ -37,17 +37,32 @@ DEAL_II_NAMESPACE_OPEN * This is in the same style of the vector view in the Trilinos * library. * + * You should consider using the VectorView object ONLY when ALL of + * the following requirements are met: + * + * 1. Your application requires a Vector object. + * + * 2. All you have at your disposal is a Number* pointer. + * + * 3. You are ABSOLUTELY SURE that the above pointer points to a + * valid area of memory of the correct size. + * + * 4. You really believe that making a copy of that memory would be + * too expensive. + * + * 5. You really know what you are doing. + * * Notice that NO CHECKS are performed on the actual memory, and if * you try to access illegal areas of memory, your computer will - * suffer from it. Use this class ONLY if you know exactly what you - * are doing. Two constructors are provided. One for read-write - * access, and one for read only access. + * suffer from it. Once again, use this class ONLY if you know exactly + * what you are doing. * - * You are allowed to use this class on objects of type const - * Vector, however you should be aware of the fact that the - * constness of pointed to array is casted away, which means that you - * should only use the const constructor when the actual object you - * are constructing is itself a constant object. + * Two constructors are provided. One for read-write access, and one + * for read only access, and you are allowed to use this class on + * objects of type const Number*, however you should be aware of the + * fact that the constness of pointed to array is casted away, which + * means that you should only use the const constructor when the + * actual object you are constructing is itself a constant object. * * You WILL be allowed to change the vector afterwards, so make sure * you know what you are doing, before you change data without @@ -136,6 +151,56 @@ public: /** This desctructor will only reset the internal sizes and the * interanl pointers, but it will NOT clear the memory. */ ~VectorView(); + + /** The reinit function of this object has a behavior which is + * different from the one of the base class. VectorView does not + * handle memory, and you should not attempt to resize the memory + * that is pointed to by this object using the reinit + * function. You can, however, resize the view that you have of + * the original object. Notice that it is your own responsability + * to ensure that the memory you are pointing to is big enough. + * + * Similarly to what happens in the base class, if fast is false, + * then the entire content of the vector is set to 0, otherwise + * the content of the memory is left unchanged. + * + * Notice that the following snippet of code may not produce what + * you expect: + * + // Create a vector of length 1. + Vector long_vector(1); + + // Make a view of it + VectorView view_of_long_vector(1, long_vector.begin()); + + // Resize the original vector to a bigger size + long_vector.reinit(100); + + // And the view, leaving the memory untouched + view_of_long_vector.reinit(100, true); + + * + * In the above case, the Vector::reinit method is called, + * and a NEW area of memory is reserved, possibly not starting at + * the same place as before. Hoever, the VectorView object + * keeps pointing to the same old area. After the two reinits, any + * call to view_of_long_vector(i), with i>0 might cause an attempt + * to access invalid areas of memory, or might function properly, + * depending on wether or not the system was able to allocate some + * memory consecutively after the original allocation. + * + * In any case, you should not rely on this behavior, and you + * should only call this reinit function if you really know what + * you are doing. + */ + virtual void reinit (const unsigned int N, + const bool fast=false); + + + /** This function is here to prevent memory corruption. It should + * never be called, and will throw an exception if you try to do + * so. */ + virtual void swap (Vector &v); }; @@ -175,6 +240,24 @@ VectorView::~VectorView() { this->val = 0; } + + +template +inline +void VectorView::reinit(const unsigned int N, const bool fast) { + this->vec_size = N; + this->max_vec_size = N; + if(fast == false) + Vector::operator=(static_cast(0)); +} + + +template +inline +void VectorView::swap(Vector &) { + AssertThrow(false, ExcMessage("Cant' swap a VectorView with a Vector!")); +} + DEAL_II_NAMESPACE_CLOSE #endif