This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
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));
}