Re: Assigning value of unassigned iterator
On 24 Aug., 23:00, backminator <backmina...@gmail.com> wrote:
I've been running c++ code under Linux gcc 2.93->4.4.3, OSX, and
Windows (VisualStudio 2005-2008) for > 3 years.
Now we are upgrading to VS2010 which supports C++00. We now suddenly
got a problem related to iterators.
The question is really, is the code below valid or not? It runs ok on
every instance of a compiler I can get my hands on, except VS2010.
It crasches on the assignment of the iterator, where it is trying to
dereference a null pointer.
My question is not really about this and that implementation of
compiler, its more of a C++, is this ok question.
Using unassigned iterators is not valid. The question is what the
below example shows?
It is a snippet from a larger code, where we have a container
containing a pair, containing an iterator.
So something like: std::vector<std::pair<int,
std::list<int>::iterator> >
So at any point, where you happens to assign a valid iterator the
value of an unassigned one, it crasches in VisualStudio 2010.
We might be able to refactor all the code having iterators in the
default constructor of the class, but Im not sure we want to ;-)
#include <list>
int main()
{
typedef std::list< int > IntList;
IntList integerList;
typedef IntList::iterator IntIterator;
IntIterator it1 = hej.end();
IntIterator it2;
it1 = it2;
Here you are attempting to read the value of
a potentially non-initialized variable. Any
operation different from destroying or assigning
*to* an uninitialized object causes undefined
behaviour.
return 0;
}
More elaborated example that show why we need this to work (and it
does in all C++ compilers except VS2010).
#include <list>
int main() {
typedef std::list< int > IntList;
typedef IntList::iterator IntIterator;
IntList integerList;
struct A
{
IntIterator it;
};
A a, b;
a.it = integerList.end();
a = b; // << here it crasches due to the test:
_Adopt(_Right._Myproxy->_Mycont); in xutility (STL)
return 0;
}
The iterator requirements allow for types that
are uninitialized after default-initialization.
This basically means that above code may or may
not cause undefined behaviour depending on the
fact, whether default-initialization leads to
such a "partially-formed" state. To prevent this
problem, you just need to ensure that your
iterator source is value-initialized, based on
[iterator.requirements.general]/6:
"Results of most expressions are undefined for
singular values; the only exceptions are destroying
an iterator that holds a singular value, the
assignment of a non-singular value to an iterator
that holds a singular value, and, for iterators
that satisfy the DefaultConstructible requirements,
using a value-initialized iterator as the source
of a copy or move operation."
[Note that the term "singular value" is misleading
in this context, see library issue #1213, but that
is a different side-aspect of this description].
Independent on the question how to make that work
I still wonder why you expect that given;
T x, y;
you are requiring that
x = y;
"works". The DefaultConstructible requirements
specifically allow for an uninitialized object
state, but don't allow for reading it. Thus, I
don't see any convincing rationale provided that
would explain your rather strong assertion for
an "example that show why we need this to work".
Why is this so important to make it work? Assuming,
you have such reason, just change
struct A
{
IntIterator it;
};
A a, b;
to
struct A
{
IntIterator it;
};
A a = {}, b = {};
which guarantees value-initialization.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]