]> https://gitweb.dealii.org/ - dealii-svn.git/commitdiff
Made Vector::reinit virtual, to avoid memory corruption in VectorView
authorheltai <heltai@0785d39b-7218-0410-832d-ea1e28bc413d>
Sun, 12 Apr 2009 09:00:53 +0000 (09:00 +0000)
committerheltai <heltai@0785d39b-7218-0410-832d-ea1e28bc413d>
Sun, 12 Apr 2009 09:00:53 +0000 (09:00 +0000)
git-svn-id: https://svn.dealii.org/trunk@18598 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/lac/include/lac/vector.h
deal.II/lac/include/lac/vector.templates.h
deal.II/lac/include/lac/vector_view.h

index 3bac18a7e05331bc0042282850967832eb7c95b1..cc6aa2ddcc2b58795ccaf10062d07ee58627f9c0 100644 (file)
@@ -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
                                      * <tt>swap(u,v)</tt> that simply calls
                                      * <tt>u.swap(v)</tt>, again in analogy
                                      * to standard functions.
-                                     */
-    void swap (Vector<Number> &v);
+                                     *
+                                     * This function is virtual in
+                                     * order to allow for derived
+                                     * classes to handle memory
+                                     * separately.
+                                     */ 
+    virtual void swap (Vector<Number> &v);
     
                                     /**
                                       * Set all components of the vector to
@@ -1179,6 +1189,21 @@ Vector<Number>::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 <typename Number>
+inline
+void
+Vector<Number>::swap (Vector<Number> &v)
+{
+  std::swap (vec_size,     v.vec_size);
+  std::swap (max_vec_size, v.max_vec_size);
+  std::swap (val,          v.val);
+}
+
+
+
 
 /*! @addtogroup Vectors
  *@{
index c6aad6382717ae64f2e0d05c7b3c316ed3ab0da0..20555a62b9c40cf184f81350b3b8edc47a2046e3 100644 (file)
@@ -239,16 +239,17 @@ void Vector<Number>::reinit (const Vector<Number2>& v,
   reinit (v.size(), fast);
 }
 
-
-
-template <typename Number>
-void
-Vector<Number>::swap (Vector<Number> &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 <typename Number>
+// void
+// Vector<Number>::swap (Vector<Number> &v)
+// {
+//   std::swap (vec_size,     v.vec_size);
+//   std::swap (max_vec_size, v.max_vec_size);
+//   std::swap (val,          v.val);
+// }
 
 
 
index 20038ec37f1e0e3fdb0a4ba487983a0e0229d0a6..28d6839fae18b8efbaecea069d85304f1cdb6fc5 100644 (file)
@@ -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<Number> 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<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.
+ * 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:
+     * <code>
+     // Create a vector of length 1.
+     Vector<double> long_vector(1);
+     
+     // Make a view of it
+     VectorView<double> 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);
+     </code>
+     *
+     * In the above case, the Vector<double>::reinit method is called,
+     * and a NEW area of memory is reserved, possibly not starting at
+     * the same place as before. Hoever, the VectorView<double> 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<Number> &v);
 };
 
 
@@ -175,6 +240,24 @@ VectorView<Number>::~VectorView() {
     this->val = 0;
 }
 
+
+
+template<typename Number>
+inline
+void VectorView<Number>::reinit(const unsigned int N, const bool fast) {
+    this->vec_size = N;
+    this->max_vec_size = N;
+    if(fast == false)
+       Vector<Number>::operator=(static_cast<Number>(0));
+}
+
+
+template<typename Number>
+inline
+void VectorView<Number>::swap(Vector<Number> &) {
+    AssertThrow(false, ExcMessage("Cant' swap a VectorView with a Vector!"));
+}
+
 DEAL_II_NAMESPACE_CLOSE
 
 #endif

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.