This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: debug/vector anomalous behaviour


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));
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]