471,305 Members | 1,352 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,305 software developers and data experts.

STL list code fires assertion in VC++ 2005, but not in VC++ 2003.

I'm getting an assertion fire from a list iterator being checked
against NULL. This did not occur in VC++ 2003 (v7.1). Are there
changes that have been made to the STL between these versions that I
should know about? Any resources I should check into?

thanks,
Jason

Jun 28 '07 #1
27 2611
Jason Doucette wrote:
I'm getting an assertion fire from a list iterator being checked
against NULL.
Why are you doing that?
This did not occur in VC++ 2003 (v7.1). Are there
changes that have been made to the STL between these versions that I
should know about?
Probably. Actually, very likely.
Any resources I should check into?
FAQ 5.8

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 28 '07 #2
I'm getting an assertion fire from a list iterator being checked
against NULL.

Why are you doing that?
Because I have a function that reports whether or not an element is in
the list. If it is, it returns an iterator to that element. If it's
not, then it returns NULL.

Is this bad? It worked fine in VC++ 2003. But, the internals of the
STL list class doesn't seem to like it, anymore.
This did not occur in VC++ 2003 (v7.1). Are there
changes that have been made to the STL between these versions that I
should know about?

Probably. Actually, very likely.
I recall reading something a long time ago that they had made some
changes. I can't seem to find a decent resource on this, though.
Any resources I should check into?

FAQ 5.8
Of what manual? The C++ Standard? I don't think it's publicly
available.

Thanks, Victor.

Jason

Jun 28 '07 #3
FAQ 5.8

Sorry, you mean the newsgroup FAQ, obviously, duh. I had forgotten
which newsgroup I was replying to.

cheers,
Jason

Jun 28 '07 #4
Sorry, you mean the newsgroup FAQ, obviously, duh. I had forgotten
which newsgroup I was replying to.
....which is parashift.com's C++ FAQ Lite, which is not a FAQ just for
this group.

5.8 is about posting non-working code questions:
http://www.parashift.com/c++-faq-lit...t.html#faq-5.8
Is this what you mean?

If so, I am not asking anyone to fix my code. I'm looking for a
resource (that I can research myself) about what changes were made to
the STL implementation from VC++ 2003 to VC++ 2005, so I can determine
what I'm now doing wrong.

Thanks,
Jason

Jun 28 '07 #5
Jason Doucette <jd*******@gmail.comwrote:
I'm getting an assertion fire from a list iterator being checked
against NULL. This did not occur in VC++ 2003 (v7.1). Are there
changes that have been made to the STL between these versions that I
should know about? Any resources I should check into?
MS added "checked iterators" in VS 2005. See:
http://msdn2.microsoft.com/en-us/lib...65(VS.80).aspx

If you need more info on them, you should probably consult a Visual
Studio group.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jun 28 '07 #6
On 2007-06-28 21:30, Jason Doucette wrote:
I'm getting an assertion fire from a list iterator being checked
against NULL. This did not occur in VC++ 2003 (v7.1). Are there
changes that have been made to the STL between these versions that I
should know about? Any resources I should check into?
No, the STL is probably the same. But the implementation in VS might
have changed. Consider yourself lucky this probably means you have
uncovered a hidden bug in your code. By the way, what do you mean with
the iterator being checked against NULL? Who did the check?

--
Erik Wikström
Jun 28 '07 #7
Jason Doucette <jd*******@gmail.comwrote:
I'm getting an assertion fire from a list iterator being checked
against NULL.

Why are you doing that?

Because I have a function that reports whether or not an element is in
the list. If it is, it returns an iterator to that element. If it's
not, then it returns NULL.
Oh, I misinterpreted your original post. For containers, usually
functions that work with them are passed a start iterator
(container.begin()) and a one-past-the-last iterator (container.end()).
If the element isn't found, then the one-past-the-last iterator is
returned.
Is this bad? It worked fine in VC++ 2003. But, the internals of the
STL list class doesn't seem to like it, anymore.
Pointers are valid iterators, so my guess is that in VC++ 2003, the
iterators were implemented as pointers, so the comparison with NULL
worked. But then, in 2005, they added the checked iterators, which is
probably a whole class instead of a simple pointer, so the comparison
with NULL is no longer valid.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jun 28 '07 #8
MS added "checked iterators" in VS 2005. See:http://msdn2.microsoft.com/en-us/lib...65(VS.80).aspx

Marcus, this link lead me to the page I was looking for:

Breaking Changes in the Standard C++ Library
http://msdn2.microsoft.com/en-us/lib...46(VS.80).aspx

Specifically, this section:

"Debug Iterators
Applications built with a debug version of the C-Runtime Library and
which use iterators incorrectly might begin to see asserts at runtime.
To disable these asserts, you must define _HAS_ITERATOR_DEBUGGING to
0. For more information, see Debug Iterator Support."

So, I have been using iterators incorrectly this entire time. Perhaps
it has to do with me setting them to NULL, or not initializing them
explicitly to a value that makes sense. I am not sure, I'll have to
research this.

Thanks for your help,
Jason

Jun 28 '07 #9
Jason Doucette wrote:
>Sorry, you mean the newsgroup FAQ, obviously, duh. I had forgotten
which newsgroup I was replying to.

...which is parashift.com's C++ FAQ Lite, which is not a FAQ just for
this group.

5.8 is about posting non-working code questions:
http://www.parashift.com/c++-faq-lit...t.html#faq-5.8
Is this what you mean?

If so, I am not asking anyone to fix my code. I'm looking for a
resource (that I can research myself) about what changes were made to
the STL implementation from VC++ 2003 to VC++ 2005, so I can determine
what I'm now doing wrong.

Thanks,
Jason
Victor was almost certainly trying to hint that you should post some
code. Without seeing code that demonstrates the error, the best we can
do is guess.

From the rest of this thread, it appears to me that you are under the
impression that iterators are pointers, which is not (necessarily) true.
Setting an iterator to NULL, for example, doesn't make any sense. You
should treat an iterator as an opaque object that can only be used in
the expressions guaranteed by the standard. If you don't have a copy of
the standard, the following is reasonably close to correct:
http://www.sgi.com/tech/stl/table_of_contents.html

The equivalent of a NULL pointer for iterators is the past-the-end
iterator (what you get from container.end()). The correct way to do
what you described elsewhere in the thread would look something like this:

template <typename T>
typename std::list<T>::iterator some_algorithm(
const std::list<T& lst, const T & value)
{
// Do whatever and return an iterator.

// Not found, return the past the end iterator.
return lst.end();
}

void some_function()
{
std::list<intlst;
// ...

std::list<int>::iterator i = some_algorithm(lst, 42);
if (i == lst.end())
{
// Handle not found case.
}
}

--
Alan Johnson
Jun 28 '07 #10
Jason Doucette <jd*******@gmail.comwrote:
So, I have been using iterators incorrectly this entire time. Perhaps
it has to do with me setting them to NULL, or not initializing them
explicitly to a value that makes sense.
Yes, I think this is the case. See Alan Johnson's post or my other post
for suggestions on how you should handle the not-found case instead of
trying to return NULL.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jun 28 '07 #11
No, the STL is probably the same. But the implementation in VS might
have changed. Consider yourself lucky this probably means you have
uncovered a hidden bug in your code. By the way, what do you mean with
the iterator being checked against NULL? Who did the check?
I have a function that checks a list for some data, by iterating
through it. If it finds the element, it returns the iterator to it.
If not, it returns NULL. The caller of this function checks the
return value (an iterator) to see if it's NULL or not. (Kind of like
a pointer, it either points to something, or NULL...)

std::list<myStructmyList;
std::list<myStruct>::iterator myIterator;

for (myIterator = myList.begin(); myIterator != myList.end();
myIterator++)
{
if (myIterator != NULL) <----- BANG!
}

thanks,
Jason

Jun 28 '07 #12
Oh, I misinterpreted your original post. For containers, usually
functions that work with them are passed a start iterator
(container.begin()) and a one-past-the-last iterator (container.end()).
If the element isn't found, then the one-past-the-last iterator is
returned.
Oh... so I should probably use this concept, as well. To be
consistent. In fact, it may be the only correct way to do it.

I should note that the assertion fires when the iterator is NOT NULL,
but is a legit element. It appears that it cannot be compared to
NULL. It used to be ok to treat it like any old pointer (perhaps
because VC++ 7.1 didn't care), but now it seems this is not ok (which
was likely always the case, for STL).
Pointers are valid iterators, so my guess is that in VC++ 2003, the
iterators were implemented as pointers, so the comparison with NULL
worked. But then, in 2005, they added the checked iterators, which is
probably a whole class instead of a simple pointer, so the comparison
with NULL is no longer valid.
Right. The checked iterators do check that they are in range. But,
my issue isn't an out-of-range one (although, eventually, it will be
when the function that does a search fails, and wants to return
NULL). My current issue is that an iterator that points to a real
element cannot be compared to NULL. Your diagnosis sounds correct.

Thanks, Marcus
Jason

Jun 28 '07 #13
Victor was almost certainly trying to hint that you should post some
code. Without seeing code that demonstrates the error, the best we can
do is guess.
Right. I didn't want people to solve my code problem. I just wanted
a resource section so I could solve it myself. But, you guys have
done an amazing job, nonetheless.
From the rest of this thread, it appears to me that you are under the
impression that iterators are pointers, which is not (necessarily) true.
Setting an iterator to NULL, for example, doesn't make any sense. You
should treat an iterator as an opaque object that can only be used in
the expressions guaranteed by the standard.
I think this is exactly my problem.
If you don't have a copy of
the standard, the following is reasonably close to correct:
http://www.sgi.com/tech/stl/table_of_contents.html
Thank you.
The equivalent of a NULL pointer for iterators is the past-the-end
iterator (what you get from container.end()). The correct way to do
what you described elsewhere in the thread would look something like this:

template <typename T>
typename std::list<T>::iterator some_algorithm(
const std::list<T& lst, const T & value)
{
// Do whatever and return an iterator.

// Not found, return the past the end iterator.
return lst.end();
}

void some_function()
{
std::list<intlst;
// ...

std::list<int>::iterator i = some_algorithm(lst, 42);
if (i == lst.end())
{
// Handle not found case.
}
}
Right, thanks a lot, Alan! This is exactly what I will need to
change.

Jason

Jun 28 '07 #14
Jason Doucette wrote:
>No, the STL is probably the same. But the implementation in VS might
have changed. Consider yourself lucky this probably means you have
uncovered a hidden bug in your code. By the way, what do you mean
with the iterator being checked against NULL? Who did the check?

I have a function that checks a list for some data, by iterating
through it. If it finds the element, it returns the iterator to it.
If not, it returns NULL. The caller of this function checks the
return value (an iterator) to see if it's NULL or not. (Kind of like
a pointer, it either points to something, or NULL...)

std::list<myStructmyList;
std::list<myStruct>::iterator myIterator;

for (myIterator = myList.begin(); myIterator != myList.end();
myIterator++)
{
if (myIterator != NULL) <----- BANG!
}
This code isn't even remotely close to the real code, Jason. There
is no "function", there is no "caller"...

Does the caller have access to the list? If he does, returning the
'end()' is much better than relying on the iterator's comparability
with NULL. It he does not, why does it have to be an iterator? Make
your function return a pointer, to the contained element if success
and NULL if not.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 28 '07 #15
This code isn't even remotely close to the real code, Jason. There
is no "function", there is no "caller"...
Sorry, I determined the function / caller wasn't the issue. It was
the iterator being compared to NULL, when it was set to being
something legitimate (between myList.begin() and myList.end()). So,
instead of making the problem more complex, I shortened it down as
much as I could, to remove all things that were irrelevant.

I believe the issue is resolved... I've been using iterators like
pointers, which is no longer safe since the switch from VC++7.1 to VC+
+8.0, as mentioned a few times elsewhere. So, I'll rework my code as
you and others have suggested, and I am confident it will work. I'll
post back and let you know.
Does the caller have access to the list? If he does, returning the
'end()' is much better than relying on the iterator's comparability
with NULL. It he does not, why does it have to be an iterator? Make
your function return a pointer, to the contained element if success
and NULL if not.
Yes, the caller does have access to the list, so returning end() is an
option, and sounds like something much better to use. I didn't know
it was standard practice to use this for something "out of range". (I
guess pointers / NULL just seemed intuitive.)

The caller makes use of the information within the element it gets (if
not NULL), and then deletes it from the list. So, having the iterator
to this element is ideal, since deleting it via erase() is very easy,
as it takes in an iterator to the element you want erased.

Thanks for your time,
Jason

Jun 28 '07 #16
On 28 Jun, 22:53, Jason Doucette <jdouce...@gmail.comwrote:
Does the caller have access to the list? If he does, returning the
'end()' is much better than relying on the iterator's comparability
with NULL. It he does not, why does it have to be an iterator? Make
your function return a pointer, to the contained element if success
and NULL if not.

Yes, the caller does have access to the list, so returning end() is an
option, and sounds like something much better to use. I didn't know
it was standard practice to use this for something "out of range". (I
guess pointers / NULL just seemed intuitive.)

The caller makes use of the information within the element it gets (if
not NULL), and then deletes it from the list. So, having the iterator
to this element is ideal, since deleting it via erase() is very easy,
as it takes in an iterator to the element you want erased.
It is ideal - and that's not by happy coincidence, it's by design. Now
you've discovered the idomatic way to use iterators, have a look at
how the standard library algoriths fit together with containers and
iterators. For example, it sounds like there could be a way to replace
your function with a single call to std::find. Might or might not be
easy - and if it is, it might or might not be worth it if you've got
your function already written and tested, but it will be useful
knowledge for next time.

Gavin Deane

Jun 28 '07 #17
Jason Doucette wrote:
My current issue is that an iterator that points to a real
element cannot be compared to NULL.
Technically, that's always been the case.
Jun 28 '07 #18
On Jun 28, 11:53 pm, Jason Doucette <jdouce...@gmail.comwrote:

[...]
Does the caller have access to the list? If he does, returning the
'end()' is much better than relying on the iterator's comparability
with NULL. It he does not, why does it have to be an iterator? Make
your function return a pointer, to the contained element if success
and NULL if not.
Yes, the caller does have access to the list, so returning end() is an
option, and sounds like something much better to use. I didn't know
it was standard practice to use this for something "out of range". (I
guess pointers / NULL just seemed intuitive.)
It's the usual solution when the user is aware of the list.
Another, more general solution is to use Barton and Nackman's
Fallible as a return value.
The caller makes use of the information within the element it gets (if
not NULL), and then deletes it from the list. So, having the iterator
to this element is ideal, since deleting it via erase() is very easy,
as it takes in an iterator to the element you want erased.
This sounds like something Fallible was designed for. The
client has no need to "know" anything about the list.

--
James Kanze (GABI Software) email:ja*********@gmail.com
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

Jun 29 '07 #19
It is ideal - and that's not by happy coincidence, it's by design.

Yes.
Now
you've discovered the idomatic way to use iterators, have a look at
how the standard library algoriths fit together with containers and
iterators. For example, it sounds like there could be a way to replace
your function with a single call to std::find. Might or might not be
easy - and if it is, it might or might not be worth it if you've got
your function already written and tested, but it will be useful
knowledge for next time.
I didn't use std::find, since I had to search for a match of a struct
field, in a list of such structs. But, I could have defined the
equality operator == for this struct, and used std::find. The actual
search code is so small (just a simple for loop), that it's no big
deal, really. But, I'll keep this in mind for the next time.

Jason
Jun 29 '07 #20
element cannot be compared to NULL.
>
Technically, that's always been the case.
Yes, I am aware of that. VC++ 7.1's implementation merely allowed me
to use them as pointers. I could just turn off VC++ 8.0's debug
warnings, but I'd rather code correctly, and leave all warnings on.

Jason
Jun 29 '07 #21
Yes, the caller does have access to the list, so returning end() is an
option, and sounds like something much better to use. I didn't know
it was standard practice to use this for something "out of range". (I
guess pointers / NULL just seemed intuitive.)

It's the usual solution when the user is aware of the list.
Another, more general solution is to use Barton and Nackman's
Fallible as a return value.
The caller makes use of the information within the element it gets (if
not NULL), and then deletes it from the list. So, having the iterator
to this element is ideal, since deleting it via erase() is very easy,
as it takes in an iterator to the element you want erased.

This sounds like something Fallible was designed for. The
client has no need to "know" anything about the list.
James, can you elaborate on Barton and Nackman's Fallible? I will
research it right now, since it sounds like what I need.

An issue that remains is that I have a pointer to the list. If the
pointer is NULL, the list doesn't even exist. Thus, I cannot return
myList.end() in such a case. (Incidentally, the reason I use a
pointer is so I can check the list's constructor for errors -- I am
very picky about error checking).

Thanks,
Jason

Jun 29 '07 #22
Jason Doucette <jd*******@gmail.comwrote:
An issue that remains is that I have a pointer to the list. If the
pointer is NULL, the list doesn't even exist. Thus, I cannot return
myList.end() in such a case. (Incidentally, the reason I use a
pointer is so I can check the list's constructor for errors -- I am
very picky about error checking).
The common idiom for constructor errors is to have the constructor throw
an exception.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jun 29 '07 #23
The common idiom for constructor errors is to have the constructor throw
an exception.
Yes. A lot of code have STL containers as globals, seemingly
oblivious to the fact that their constructors are being run (even just
to create an empty list) without any code to catch that exception.

So, I use use a pointer to the list, and make that global, instead.
Then, the creation of the list can exist in code that catches any
constructor exceptions.

Jason

Jun 29 '07 #24
Jason Doucette <jd*******@gmail.comwrote in news:1183149322.923752.155870
@k79g2000hse.googlegroups.com:
>The common idiom for constructor errors is to have the constructor throw
an exception.

Yes. A lot of code have STL containers as globals, seemingly
oblivious to the fact that their constructors are being run (even just
to create an empty list) without any code to catch that exception.

So, I use use a pointer to the list, and make that global, instead.
Then, the creation of the list can exist in code that catches any
constructor exceptions.
Out of curiosity... what exception do you expect your list's constructor to
throw? (Assuming default constructor for the list)
Jun 29 '07 #25
Andre Kostur wrote:
Jason Doucette <jd*******@gmail.comwrote in
news:1183149322.923752.155870 @k79g2000hse.googlegroups.com:
>>The common idiom for constructor errors is to have the constructor throw
an exception.

Yes. A lot of code have STL containers as globals, seemingly
oblivious to the fact that their constructors are being run (even just
to create an empty list) without any code to catch that exception.

So, I use use a pointer to the list, and make that global, instead.
Then, the creation of the list can exist in code that catches any
constructor exceptions.

Out of curiosity... what exception do you expect your list's constructor
to throw? (Assuming default constructor for the list)
It could throw a bad_alloc. If the list uses an extra node as the past_end
node, the pointer to which is returned by end(), then there could be an
allocation even for the empty list.
Best

Kai-Uwe Bux
Jun 29 '07 #26
On Jun 29, 9:49 pm, Jason Doucette <jdouce...@gmail.comwrote:
James, can you elaborate on Barton and Nackman's Fallible? I will
research it right now, since it sounds like what I need.
It's the "standard" solution anytime a function might not be
able to return a legitimate value. In its simplest form:

template< typename T >
class Fallible
{
public:
Fallible()
: myIsValid( false )
{}
Fallible( T const& value )
: myIsValid( true )
, myValue( value )
{}

bool isValid() const
{
return myIsValid ;
}

T const& value() const
{
assert( myIsValid ) ;
return myValue ;
}
private:
bool myIsValid ;
T myValue ;
} ;

For a version with all sorts of bells and whistles (and which
really goes beyond the concept of Fallible, and should probably
be several different classes), see the code at my site
(kanze.james.neuf.fr//code-en.html---subsystem Basic, component
Fallible). The one extension there that you probably do want is
the member function "elseDefaultTo()"; the rest is really
support for other uses.

--
James Kanze (Gabi Software) email: ja*********@gmail.com
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

Jun 30 '07 #27
Out of curiosity... what exception do you expect your list's constructor to
throw? (Assuming default constructor for the list)
std::bad_alloc is the C++ standard for out of memory exceptions, which
is what the STL uses. Actually, it doesn't specifically use it, it's
just uses C++'s new internally, and this throws std::bad_alloc when it
fails, so the STL throws std::bad_alloc as a result.

Be cautious if you're using VC++ 6.0 or earlier since, without proper
attention, the default behaviour doesn't match the C++ standard; it
returns NULL.

Jason

Jul 1 '07 #28

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

reply views Thread by Guohui He | last post: by
11 posts views Thread by Peter Oliphant | last post: by
7 posts views Thread by Mihajlo Cvetanović | last post: by
5 posts views Thread by techie | last post: by
reply views Thread by ashukasama | last post: by
2 posts views Thread by Allen Maki | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.