debug/vector anomalous behaviour

Stefano Soffia soffia@cs.unipr.it
Sun May 11 10:29:00 GMT 2008


On Sat, 10 May 2008, PAOLO.CARLINI@ORACLE.COM wrote:

> Ok, many thanks to everyone for the explanations. I'm going to commit to
> mainline and 4_3-branch the below, tested x86_64-linux.

Sorry, maybe I am wrong but I suspect that this will only shift the problem
to another place.

   $ pwd
   /usr/lib/gcc/i686-pc-linux-gnu/4.2.3/include/g++-v4/debug

   $ diff -u vector.old vector
   --- vector.old  2008-05-10 19:29:00.000000000 +0200
   +++ vector      2008-05-10 19:29:27.000000000 +0200
   @@ -362,7 +362,7 @@
          bool
          _M_requires_reallocation(size_type __elements)
          {
   -#ifdef _GLIBCXX_DEBUG_PEDANTIC
   +#ifndef _GLIBCXX_DEBUG_PEDANTIC
           return __elements > this->capacity();
    #else
           return __elements > _M_guaranteed_capacity;

   $ pwd
   /home/stefano/projects/test

   $ g++ -o out -D_GLIBCXX_DEBUG test.cc

   $ ./out

   $ g++ -o out -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC test.cc

   $ ./out
   /usr/lib/gcc/i686-pc-linux-gnu/4.2.3/include/g++-v4/debug/safe_iterator.h:209:
       error: attempt to increment a singular iterator.

   Objects involved in the operation:
   iterator "this" @ 0x0xbfd2bfdc {
   type =
   N11__gnu_debug14_Safe_iteratorIN9__gnu_cxx17__normal_iteratorIPjNSt6__norm6vector
   IjSaIjEEEEENSt7__debug6vectorIjS6_EEEE (mutable iterator);
     state = singular;
     references sequence with type `NSt7__debug6vectorIjSaIjEEE' @ 0x0xbfd2bfdc
   }
   Aborted

The patch should be something similar to:

--- vector.old	2008-05-10 19:29:00.000000000 +0200
+++ vector	2008-05-10 19:51:19.000000000 +0200
@@ -177,7 +177,16 @@
  	  this->_M_invalidate_all();
        }

-      using _Base::capacity;
+      size_type
+      capacity() const
+      {
+	#ifdef _GLIBCXX_DEBUG_PEDANTIC
+	    return _M_guaranteed_capacity;
+	#else
+	    return _Base::capacity();
+	#endif
+      }
+
        using _Base::empty;

        void
@@ -362,11 +371,7 @@
        bool
        _M_requires_reallocation(size_type __elements)
        {
-#ifdef _GLIBCXX_DEBUG_PEDANTIC
  	return __elements > this->capacity();
-#else
-	return __elements > _M_guaranteed_capacity;
-#endif
        }

        void

i.e. the distinction between pedantic vs non-pedantic should be moved
inside the capacity() method.

But look, maybe I'm missing some details. I tested the patch against the test
case and also in our project. It seems to work correctly, indeed with the above
patch, compiling in pedantic mode, we discovered some assumptions that I was
making about the behaviour of the clear() method which are not specified by the
standard (so, thanks to the author of the debug mode because it is really useful!)

Stefano Soffia
Applied Formal Methods Laboratory
Department of Mathematics, University of Parma, Italy
http://www.cs.unipr.it/afmlab/

(PS: the test case can be simplified a little. It is not very interesting,
however this is the code. The trick remains the same.)

#include <vector>
#include <algorithm>
#include <iterator>

typedef std::vector<unsigned> array_t;
typedef std::back_insert_iterator<array_t> bii_t;

array_t a;

int main() {
   // Push 3 elements.
   a.push_back(0);
   a.push_back(1);
   a.push_back(2);
   // Ensure that there is enough space for another element.
   // (1 + 3 = 4)
   if (a.capacity() < 4)
     a.reserve(4);
   // Add two new elements.
   std::copy(a.begin(),
             a.begin() + 1,
             bii_t(a));
}



More information about the Libstdc++ mailing list