C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

stl iterator specification
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
lukeshen
Guest





PostPosted: Sun Aug 22, 2004 3:04 am    Post subject: stl iterator specification Reply with quote



Hi, in my recent project, I am trying to implement some STL-style
iterators (forward and bidirectional). So I give stl iterator some
serious thought, in terms of how it behaves if it is not used in the
conventional way. The following test code represents 3 legal but
questionable usages of iterator. Legal means the code compiles fine (or
maybe with warnings depend on compiler). Questionable means the result
seems to be undefined at the best, crash at the worst.

Here is the code:

#include <iostream>
#include <vector>


using namespace std;


int main()
{
cout << "test dangling pointer" << endl;
vector p_vi->push_back(1);
p_vi->push_back(2);


vector<int>::iterator iter = p_vi->begin();


cout << "before delete p_vi:" << *iter << endl;
delete p_vi;
cout << "after delete p_vi, before iter++:" << *iter << endl;
iter++;
cout << "after iter++:" << *iter << endl;


cout << "test sentinel iterator" << endl;
vector vi.push_back(1);
vi.push_back(2);


vector<int>::iterator iter2 = vi.end();
cout << "before iter2++:" << *iter2 << endl;
iter2++;
cout << "after iter2++:" << *iter2 << endl;


cout << "test null iterator" << endl;
vector cout << "before iter3++:" << *iter3 << endl;
iter3++;
cout << "after iter3++:" << *iter3 << endl;


return 0;
}

The code compiles without any warning with gcc 3.2.2. And the output is:

test dangling pointer
before delete p_vi:1
after delete p_vi, before iter++:134521432
after iter++:2
test sentinel iterator
before iter2++:134521448
after iter2++:2
test null iterator
Segmentation fault

As far as my current project is concerned, I feel that it would be
better to write my own iterator in a way that such questionable usage of
iterator becomes a compile-time error. But I would like to find out what
the standard says about such usage of iterator.

Any pointer will be greatly appreciated.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Maxim Yegorushkin
Guest





PostPosted: Sun Aug 22, 2004 11:06 pm    Post subject: Re: stl iterator specification Reply with quote



lukeshen wrote:

[]

Quote:
As far as my current project is concerned, I feel that it would be
better to write my own iterator in a way that such questionable usage of
iterator becomes a compile-time error. But I would like to find out what
the standard says about such usage of iterator.

It's very unlikely that you could catch those errors at compile time. But you certainly may catch them at runtime - this is what STLPort does in debug mode.

--
Maxim Yegorushkin

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
llewelly
Guest





PostPosted: Mon Aug 23, 2004 10:26 am    Post subject: Re: stl iterator specification Reply with quote



lukeshen <lukeshen (AT) earthlink (DOT) net> writes:
[snip]
Quote:
int main()
{
cout << "test dangling pointer" << endl;
vector p_vi->push_back(1);
p_vi->push_back(2);


vector<int>::iterator iter = p_vi->begin();


cout << "before delete p_vi:" << *iter << endl;
delete p_vi;

This destroys the vector in question, making all iterators which
point into it singular.

Quote:
cout << "after delete p_vi, before iter++:" << *iter << endl;
iter++;

Incrementing a singular iterator is undefined behavior.

Quote:
cout << "after iter++:" << *iter << endl;

And so is derferencing it.

Quote:


cout << "test sentinel iterator" << endl;
vector vi.push_back(1);
vi.push_back(2);


vector<int>::iterator iter2 = vi.end();
cout << "before iter2++:" << *iter2 << endl;

Dereferencing a past-the-end() iterator is undefined behavior.

Quote:
iter2++;

And so is incrementing it.

Quote:
cout << "after iter2++:" << *iter2 << endl;


cout << "test null iterator" << endl;
vector

This creates a singular iterator. There are 4 safe things you can do
with it:

(0) Assign it a new value.
(1) Take its address.
(2) Bind a reference to it.
(3) Destroy it.

All other operations result in undefined behavior; it can't be copied,
dereferenced, incremented, tested, passed (by value) to a
function, returned from a function, etc.

Quote:
cout << "before iter3++:" << *iter3 << endl;
iter3++;
cout << "after iter3++:" << *iter3 << endl;


return 0;
}

The code compiles without any warning with gcc 3.2.2. And the output is:

test dangling pointer
before delete p_vi:1
after delete p_vi, before iter++:134521432
after iter++:2
test sentinel iterator
before iter2++:134521448
after iter2++:2
test null iterator
Segmentation fault

I compiled and ran it thusly:
g++-3.4 -D_GLIBCXX_DEBUG -g lukeshen.cc ; ./a.out
test dangling pointer
before delete p_vi:1
/usr/local/gcc-3.4/lib/gcc/i386-unknown-freebsd5.2/3.4.0/include/c++/debug/safe_iterator.h:170:
error: attempt to dereference a singular iterator.

Objects involved in the operation:
iterator "this" @ 0x0xbfbfe8b0 {
type = N11__gnu_debug14_Safe_iteratorIN9__gnu_cxx17__normal_iteratorIPiN10__gnu_norm6vectorIiSaIiEEEEEN15__gnu_debug_def6vectorIiS6_EEEE
(mutable iterator);
state = singular;
}
after delete p_vi, before iter++:Abort (core dumped)

(*)

The other violations present in your code will also be detected,
provided your code is modified to make them reachable.

Quote:
As far as my current project is concerned, I feel that it would be
better to write my own iterator in a way that such questionable usage of
iterator becomes a compile-time error.

How do you propose to design such an interface? Whether or not the
vector an iterator points to a runtime property. Whether or not
an iterator being dereferenced is singular is a runtime
property. You can define no default constructor for your
iterator, which makes one of your examples a compile time error,
but I do not think you can make the other examples compile time
errors.

However, if you include a pointer or reference to the container inside
your iterator, it becomes relatively straightforward to detect
many (but not all, and not your delete example) unsafe uses of
iterators at runtime.

(*) I don't like the mangled names either. If you have a new enough
version of c++filt (I don't) it will demangle them.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
lukeshen
Guest





PostPosted: Mon Aug 23, 2004 10:29 am    Post subject: Re: stl iterator specification Reply with quote

Maxim Yegorushkin wrote:
Quote:
lukeshen wrote:

As far as my current project is concerned, I feel that it would be
better to write my own iterator in a way that such questionable usage of
iterator becomes a compile-time error. But I would like to find out what
the standard says about such usage of iterator.


It's very unlikely that you could catch those errors at compile time. But you certainly may catch them at runtime - this is what STLPort does
in debug mode.

It seems there are several ways to catch those errors during runtime,

such as using assertion or throwing exception. Is there a suggested way
by the language standard, or is there a preferred way in the industry?
Unfortunately, I have not used STLport yet. You mentioned that those
errors were caught during the debug mode. So I guess STLport uses
assertion, which is turned on during debug mode. Is that true?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
facman
Guest





PostPosted: Tue Aug 24, 2004 6:40 am    Post subject: Re: stl iterator specification Reply with quote



llewelly wrote:

Quote:
How do you propose to design such an interface? Whether or not the
vector an iterator points to a runtime property. Whether or not
an iterator being dereferenced is singular is a runtime
property. You can define no default constructor for your
iterator, which makes one of your examples a compile time error,
but I do not think you can make the other examples compile time
errors.

I cannot, unless I implement non-STL-style iterator. For example, end()

returns bool as a sentinel, instead of iterator. So there is no problem
of dereferencing the iterator returned by end(). (Accordingly,
operator!=() has to be overloaded.)
Nevertheless, I think the benefit of having STL-style iterator
outweighs, say the algorithm library is designed for STL-style iterators.
Thanks a lot for your info. I think I will try to comply to STL-style in
my iterator implementation.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
James Hopkin
Guest





PostPosted: Tue Aug 24, 2004 7:49 pm    Post subject: Re: stl iterator specification Reply with quote

facman <danlushen (AT) hotmail (DOT) com> wrote

Quote:

I think I will try to comply to STL-style in
my iterator implementation.


Have you considered using boost::iterator_facade to implement your
iterator?

There are very many subtle details in implementing a fully
STL-compliant iterator.

I *do* recommend writing iterators by hand for the learning
experience, but for production code, iterator_facade will give you the
bullet-proofing you need.


James

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Maxim Yegorushkin
Guest





PostPosted: Tue Aug 24, 2004 10:31 pm    Post subject: Re: stl iterator specification Reply with quote

lukeshen <lukeshen (AT) earthlink (DOT) net> wrote:

[]

Quote:
It seems there are several ways to catch those errors during runtime,
such as using assertion or throwing exception. Is there a suggested way
by the language standard, or is there a preferred way in the industry?

I think those things, like dereferencing an iterator pointing to an item of a nonexisting container, are serious coding errors that should be reported using exceptions, most preferably that no one catches, so that they dump core for the author of the code to examine.

Quote:
Unfortunately, I have not used STLport yet. You mentioned that those
errors were caught during the debug mode. So I guess STLport uses
assertion, which is turned on during debug mode. Is that true?

I don't know the details, but who cares whether it's an assertion or an exceptions as long as it works only in debug mode and the errors are reported using message box.

--
Maxim Yegorushkin

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
facman
Guest





PostPosted: Tue Aug 24, 2004 10:48 pm    Post subject: Re: stl iterator specification Reply with quote



James Hopkin wrote:

Quote:
Have you considered using boost::iterator_facade to implement your
iterator?

There are very many subtle details in implementing a fully
STL-compliant iterator.

I *do* recommend writing iterators by hand for the learning
experience, but for production code, iterator_facade will give you the
bullet-proofing you need.

It's good to know. I will look into it for reference. Nevertheless, the

environment I am working in has a fairly old compiler. As far as I know,
BOOST library does not compile on that old compiler. Upgrading compiler
is way beyond my control. But I will definitely check out
iterator_facade carefully.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Wed Aug 25, 2004 8:47 pm    Post subject: Re: stl iterator specification Reply with quote

"Maxim Yegorushkin" <e-maxim (AT) yandex (DOT) ru> wrote

Quote:
lukeshen <lukeshen (AT) earthlink (DOT) net> wrote:

[]

It seems there are several ways to catch those errors during
runtime, such as using assertion or throwing exception. Is there a
suggested way by the language standard, or is there a preferred way
in the industry?

I think those things, like dereferencing an iterator pointing to an
item of a nonexisting container, are serious coding errors that should
be reported using exceptions, most preferably that no one catches, so
that they dump core for the author of the code to examine.

If no one catches the exception, the stack still might be unwound, and
the context of the error lost. If you don't want anyone to catch the
exception, call abort (which is what assert does).

Quote:
Unfortunately, I have not used STLport yet. You mentioned that those
errors were caught during the debug mode. So I guess STLport uses
assertion, which is turned on during debug mode. Is that true?

I don't know the details, but who cares whether it's an assertion or
an exceptions as long as it works only in debug mode and the errors
are reported using message box.

Why only in debug mode? Do you wear a life jacket during the practice
exercises in the harbor, and take it off when you go to sea?

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
David Abrahams
Guest





PostPosted: Wed Aug 25, 2004 9:38 pm    Post subject: Re: stl iterator specification Reply with quote

facman <danlushen (AT) hotmail (DOT) com> writes:

Quote:
James Hopkin wrote:

Have you considered using boost::iterator_facade to implement your
iterator?

There are very many subtle details in implementing a fully
STL-compliant iterator.

I *do* recommend writing iterators by hand for the learning
experience, but for production code, iterator_facade will give you the
bullet-proofing you need.

It's good to know. I will look into it for reference. Nevertheless, the
environment I am working in has a fairly old compiler. As far as I know,
BOOST library does not compile on that old compiler. Upgrading compiler
is way beyond my control. But I will definitely check out
iterator_facade carefully.

Which compiler?

--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
David Abrahams
Guest





PostPosted: Wed Aug 25, 2004 9:39 pm    Post subject: Re: stl iterator specification Reply with quote

"Maxim Yegorushkin" <e-maxim (AT) yandex (DOT) ru> writes:

Quote:
lukeshen <lukeshen (AT) earthlink (DOT) net> wrote:

[]

It seems there are several ways to catch those errors during
runtime, such as using assertion or throwing exception. Is there a
suggested way by the language standard, or is there a preferred way
in the industry?

I think those things, like dereferencing an iterator pointing to an
item of a nonexisting container, are serious coding errors that should
be reported using exceptions, most preferably that no one catches, so
that they dump core for the author of the code to examine.

That's called an "assertion". Generally speaking, reporting coding
errors with exceptions is a terrible idea.


--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
facman
Guest





PostPosted: Thu Aug 26, 2004 7:41 am    Post subject: Re: stl iterator specification Reply with quote



David Abrahams wrote:

Quote:
It's good to know. I will look into it for reference. Nevertheless, the
environment I am working in has a fairly old compiler. As far as I know,
BOOST library does not compile on that old compiler. Upgrading compiler
is way beyond my control. But I will definitely check out
iterator_facade carefully.


Which compiler?

Sun WorkShop 7.*, if my memory is correct. (I am at home now, so I

cannot verify it.) But I heard a lot of complaints at work that Boost
does not compile on it.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
facman
Guest





PostPosted: Thu Aug 26, 2004 7:41 am    Post subject: Re: stl iterator specification Reply with quote



David Abrahams wrote:


Quote:
I think those things, like dereferencing an iterator pointing to an
item of a nonexisting container, are serious coding errors that should
be reported using exceptions, most preferably that no one catches, so
that they dump core for the author of the code to examine.


That's called an "assertion". Generally speaking, reporting coding
errors with exceptions is a terrible idea.




James Kanze wrote:

Quote:
Why only in debug mode? Do you wear a life jacket during the practice
exercises in the harbor, and take it off when you go to sea?

That is actually why I started this thread, though I failed to raise
this question explicitly. I agree with David that those wrong usage of
iterator in my test program are programming errors. Programming errors
generally should be reported with assertion, not with exception.
However, assertion only works in the debug mode, as James points out.
Code goes to exception will have assertion disabled.
So is there a third solution, other than assertion and exception? That
is why I am trying to find out what language specification says about it
regarding STL iterator.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Maxim Yegorushkin
Guest





PostPosted: Thu Aug 26, 2004 7:46 am    Post subject: Re: stl iterator specification Reply with quote

David Abrahams wrote:

Quote:
It seems there are several ways to catch those errors during
runtime, such as using assertion or throwing exception. Is there a
suggested way by the language standard, or is there a preferred way
in the industry?

I think those things, like dereferencing an iterator pointing to an
item of a nonexisting container, are serious coding errors that should
be reported using exceptions, most preferably that no one catches, so
that they dump core for the author of the code to examine.

That's called an "assertion". Generally speaking, reporting coding
errors with exceptions is a terrible idea.

If you are talking about the assertions which works only in debug builds (like assert()), I disagree. In real life one can not always be 100%
sure that her unit / functional tests have full code / case coverage, so debug mode only assertions make little sense.

--
Maxim Yegorushkin

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Maxim Yegorushkin
Guest





PostPosted: Fri Aug 27, 2004 2:44 am    Post subject: Re: stl iterator specification Reply with quote

<kanze (AT) gabi-soft (DOT) fr> wrote:

[]

Quote:
If no one catches the exception, the stack still might be unwound, and
the context of the error lost. If you don't want anyone to catch the
exception, call abort (which is what assert does).

I can only say that it's too bad that the standard allows implementations to do the unwinding if the exception is not handled.

Quote:
Unfortunately, I have not used STLport yet. You mentioned that those
errors were caught during the debug mode. So I guess STLport uses
assertion, which is turned on during debug mode. Is that true?

I don't know the details, but who cares whether it's an assertion or
an exceptions as long as it works only in debug mode and the errors
are reported using message box.

Why only in debug mode?

I am talking about the debug mode in STLPort, so please, ask not me, ask Boris Fomitchev.

Quote:
Do you wear a life jacket during the practice
exercises in the harbor, and take it off when you go to sea?

It might be that the jacket makes you so slow that it makes you useless in real action.

--
Maxim Yegorushkin

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.