Greetings,

This patch adds a lightweight self-consistency check to many vector
operations. Google issue 5246356.

Ok for google/integration branch?

Thanks,
--


2011-09-06  Paul Pluzhnikov  <ppluzhni...@google.com>

        * include/bits/stl_vector.h (__is_valid): New function.
        (begin, end, size, capacity, swap, clear): Call it.
        * include/bits/vector.tcc (operator=): Likewise.



Index: include/bits/stl_vector.h
===================================================================
--- include/bits/stl_vector.h   (revision 178493)
+++ include/bits/stl_vector.h   (working copy)
@@ -234,6 +234,16 @@
       using _Base::_M_impl;
       using _Base::_M_get_Tp_allocator;
 
+      bool __is_valid() const
+      {
+        return (this->_M_impl._M_end_of_storage == 0
+               && this->_M_impl._M_start == 0
+               && this->_M_impl._M_finish == 0)
+             || (this->_M_impl._M_start <= this->_M_impl._M_finish
+                 && this->_M_impl._M_finish <= this->_M_impl._M_end_of_storage
+                 && this->_M_impl._M_start < this->_M_impl._M_end_of_storage);
+      }
+
     public:
       // [23.2.4.1] construct/copy/destroy
       // (assign() and get_allocator() are also listed in this section)
@@ -531,7 +541,13 @@
        */
       iterator
       begin() _GLIBCXX_NOEXCEPT
-      { return iterator(this->_M_impl._M_start); }
+      {
+#if __google_stl_debug_dangling_vector
+        if (!this->__is_valid())
+          __throw_logic_error("begin() on corrupt (dangling?) vector");
+#endif
+       return iterator(this->_M_impl._M_start);
+      }
 
       /**
        *  Returns a read-only (constant) iterator that points to the
@@ -540,7 +556,13 @@
        */
       const_iterator
       begin() const _GLIBCXX_NOEXCEPT
-      { return const_iterator(this->_M_impl._M_start); }
+      {
+#if __google_stl_debug_dangling_vector
+        if (!this->__is_valid())
+          __throw_logic_error("begin() on corrupt (dangling?) vector");
+#endif
+       return const_iterator(this->_M_impl._M_start);
+      }
 
       /**
        *  Returns a read/write iterator that points one past the last
@@ -549,7 +571,13 @@
        */
       iterator
       end() _GLIBCXX_NOEXCEPT
-      { return iterator(this->_M_impl._M_finish); }
+      {
+#if __google_stl_debug_dangling_vector
+        if (!this->__is_valid())
+          __throw_logic_error("end() on corrupt (dangling?) vector");
+#endif
+       return iterator(this->_M_impl._M_finish);
+      }
 
       /**
        *  Returns a read-only (constant) iterator that points one past
@@ -558,7 +586,13 @@
        */
       const_iterator
       end() const _GLIBCXX_NOEXCEPT
-      { return const_iterator(this->_M_impl._M_finish); }
+      {
+#if __google_stl_debug_dangling_vector
+        if (!this->__is_valid())
+          __throw_logic_error("end() on corrupt (dangling?) vector");
+#endif
+       return const_iterator(this->_M_impl._M_finish);
+      }
 
       /**
        *  Returns a read/write reverse iterator that points to the
@@ -638,7 +672,13 @@
       /**  Returns the number of elements in the %vector.  */
       size_type
       size() const _GLIBCXX_NOEXCEPT
-      { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
+      {
+#if __google_stl_debug_dangling_vector
+        if (!this->__is_valid())
+          __throw_logic_error("size() on corrupt (dangling?) vector");
+#endif
+       return size_type(this->_M_impl._M_finish - this->_M_impl._M_start);
+      }
 
       /**  Returns the size() of the largest possible %vector.  */
       size_type
@@ -718,7 +758,12 @@
        */
       size_type
       capacity() const _GLIBCXX_NOEXCEPT
-      { return size_type(this->_M_impl._M_end_of_storage
+      {
+#if __google_stl_debug_dangling_vector
+        if (!this->__is_valid())
+          __throw_logic_error("capacity() on corrupt (dangling?) vector");
+#endif
+       return size_type(this->_M_impl._M_end_of_storage
                         - this->_M_impl._M_start); }
 
       /**
@@ -1112,6 +1157,10 @@
                        noexcept(_Alloc_traits::_S_nothrow_swap())
 #endif
       {
+#if __google_stl_debug_dangling_vector
+        if (!this->__is_valid() || !__x.__is_valid())
+          __throw_logic_error("swap() on corrupt (dangling?) vector");
+#endif
        this->_M_impl._M_swap_data(__x._M_impl);
        _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(),
                                  __x._M_get_Tp_allocator());
@@ -1125,7 +1174,13 @@
        */
       void
       clear() _GLIBCXX_NOEXCEPT
-      { _M_erase_at_end(this->_M_impl._M_start); }
+      {
+#if __google_stl_debug_dangling_vector
+        if (!this->__is_valid())
+          __throw_logic_error("clear() on corrupt (dangling?) vector");
+#endif
+       _M_erase_at_end(this->_M_impl._M_start);
+      }
 
     protected:
       /**
Index: include/bits/vector.tcc
===================================================================
--- include/bits/vector.tcc     (revision 178493)
+++ include/bits/vector.tcc     (working copy)
@@ -158,6 +158,10 @@
     vector<_Tp, _Alloc>::
     operator=(const vector<_Tp, _Alloc>& __x)
     {
+#if __google_stl_debug_dangling_vector
+      if (!this->__is_valid() || !__x.__is_valid())
+       __throw_logic_error("operator=() on corrupt (dangling?) vector");
+#endif
       if (&__x != this)
        {
 #ifdef __GXX_EXPERIMENTAL_CXX0X__

--
This patch is available for review at http://codereview.appspot.com/4973065

Reply via email to