problems remove()ing with std::list

This topic is 4247 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

To start off, I will describe what I am doing a bit. It may seem a bit irrelevant at the moment, but it might clarify things a bit later. I am using MSVC++ 2005 EE to create a GUI system. I have a Window class which is a standard widget/window/whatever you want to call it. A Window can have child Windows (and, hence, a parent Window). I use an std::list to keep track of which Windows are children of a Window, and a pointer to the parent Window of the Window. Now, when a Window is given input focus, it has the parent Window remove it from the list of child Windows and then add it again. My problem is with the removing of the Window from the child Windows list. I use this function:
void Window::RemoveChild(Window *removedChild)
{
//childWindows is the std::list
childWindows.remove(removedChild);
}
However, my program crashes on this line, inside of the remove() call. I get an error message of "list incrementor not incrementable" on line 236 of the list header. Now, this makes me think that removedChild isn't actually inside of remove(). But, I've looked through my code and I can't see how it could not be in there. See, the only way that a child Window can get focus is from a parent Window giving it focus. The only way that RemoveChild() is callled is form a child Window (*parentWindow is checked to be != NULL and I set parentWindow to NULL in the constructor), and it is passed this, so it's not getting the wrong pointer. I've also tried std::find() then erase()ing the found iterator, and writing my own finding algorithm. All of these get the same error that a list iterator cannot be incremented. Well, any suggestions? I don't really know what other code I could possibly show you, since it all _seems_ to be in order. Thanks in advanced.

Share on other sites
Quite posibly, the childWindows list most likely has become corrupted. This can happen if you either:
Write out out bounds from some array, or
You have multiple threads modifying this list, without explicit locking around use of the list.
I'm picking the later of these...

Share on other sites
I only have a single thread running on this program.

As for corrupted, I don't think that that is likely. I use the list in other places(eg: telling the parent window to draw makes it have all the child windows draw, too), and it works there. All that I do to the list is iterate through it for drawing and input handling (should probably use for_each()), push_back() new Windows, and remove() in this problem. I don't use any arrays in my program right now (all strings, lists, or vectors), so writing out of bounds shouldn't be a problem. Is there any way to check for corruption?

I know that iterators can become invalid when you remove it from the list. Could this be a problem? Again, I doubt that it is, seeing as Microsoft almost definately got their remove() implementation correct.

[Edited by - Ezbez on July 6, 2006 4:40:19 AM]

Share on other sites
Try doing ++childWindows.begin() in debug mode and see what it does, I suspect it'll do the same thing. Then take a look at the values of childWindows._Myhead and childWindows._Myhead->_Next in the debugger. The only times this should happen without any form of corruption would be if you were trying to increment an empty or end iterator, which can't happen inside remove().

Share on other sites
++childWindows.begin() doesn't cause a crash or error or anything. I don't do anything with this iterator other than increment it; would the problem not show up if I don't do something with the iterator?

And, odly enough, it increments fine even if there is only one child window.

Share on other sites
Try:

list<Window*>::iterator i = childWindows.begin();while (i != childWindows.end() {   if (*i == removeChild)       i = childWindows.erase(i);   else       ++i;}

And see what happens

Share on other sites
Quote:
 Original post by Ezbez++childWindows.begin() doesn't cause a crash or error or anything. I don't do anything with this iterator other than increment it; would the problem not show up if I don't do something with the iterator?And, odly enough, it increments fine even if there is only one child window.

Hmm, what's the value of _Myhead? Are you able to follow the _Next pointers in the list nodes using the debugger, and do they contain the correct number of nodes and generally seem to make sense? Since you seem to be dealing with raw pointers you should double check that you haven't accidentally deleted the current this pointer somewhere. Something like this for example:
Window* window = new Window();//...if(window->closed()) delete window;//...window->RemoveChild(child);

It could produce all manner of strange results and could even manifest itself differently with different build configurations. Your description of the process in which this is happenning sounds a bit strange aswell. Why would you remove a child from it's parent and then re-add it when focus changes?

Share on other sites
I remove it then re-add it so that it is at the back of the list and is drawn last, and hence is on top. This was the way that an article about GUIs in DirectX on this website said to do it.

Unfortunately, I'm not really able to debug it. If I try to debug it, it exits before anything happens, and doesn't tell me anything about why. It runs fine without debugging.

I sure hope that I'm not deleting my childWindows. They are on the stack (yes, I know, it shouldn't be that way). I declare both the child and its parent in the main() function, so they should get removed at the same time.

@Owl - This is almost identical to what I tried originally. It crashes, too, with a "list iterator cannot be incremented" error.

Share on other sites
Quote:
 Original post by EzbezUnfortunately, I'm not really able to debug it. If I try to debug it, it exits before anything happens, and doesn't tell me anything about why. It runs fine without debugging.

If I was you I'd be sorting this problem out first. It may be a sign that bad things are happenning else and has nothing to do with your Window class. And even if it's not related, debugging without a debugger really sucks.

Quote:
 I sure hope that I'm not deleting my childWindows. They are on the stack (yes, I know, it shouldn't be that way). I declare both the child and its parent in the main() function, so they should get removed at the same time.

BAD MONKEY!!!! Ahem....try commenting out the offending line(s) of code so that your program can run to completion and see if VS complains about the stack being corrupt or anything similarly nasty (ie. check if you've done bad things to your Window instances while they're on the stack).

Share on other sites
I'm sorry, but I don't quite understand what you mean. Which lines in particular would be the "offending" ones? The declarations of my Windows? Adding the child Windows to the parent Windows? I will test out using new on my Windows, though.

And I'm sorta sure that my problem with debugging comes from using SDL. Would I need to use a special debugging library instead of the typical SDL library?

Edit: some of my debugger output is:

"'OpenGLApplication.exe': Loaded 'C:\Documents and Settings\Owner\Desktop\Tom's Useless Junk\OpenGL Games\Gravitas\Debug\SDL.dll', Binary was not built with debug information."

Along with listing that a bunch of libraries have no symbols loaded (eg: glu32,ntdll, msvcrt, ddraw, many more).

Edit again: Using new for the Windows doesn't change a think, at least as far as I can tell.

Share on other sites
Quote:
 Original post by EzbezI'm sorry, but I don't quite understand what you mean. Which lines in particular would be the "offending" ones? The declarations of my Windows? Adding the child Windows to the parent Windows? I will test out using new on my Windows, though.

Sorry, by the offending lines I mean those which directly cause the error (eg. comment out the call to RemoveChild).

Quote:
 Original post by EzbezAnd I'm sorta sure that my problem with debugging comes from using SDL. Would I need to use a special debugging library instead of the typical SDL library?Edit: some of my debugger output is:"'OpenGLApplication.exe': Loaded 'C:\Documents and Settings\Owner\Desktop\Tom's Useless Junk\OpenGL Games\Gravitas\Debug\SDL.dll', Binary was not built with debug information."

I doubt that's the problem, most (all?) of the standard Windows DLLs you use would be built without debug information. All that means is that you can't step into the code of those DLLs and have any idea where you are, you'll only get the actual CPU instructions being executed in the disassembly view.

Share on other sites
Quote:
 Original post by joanusdmentiaSorry, by the offending lines I mean those which directly cause the error (eg. comment out the call to RemoveChild).

Well, I comment out that, and the program runs fine. Just the child Windows don't re-order based on focus.

Share on other sites
Alright, I have a fairly major update.

I compiled my project with Code::Blocks using GCC to compile. And, surprisingly, it worked perfectly. There's no crash and does what it's supposed to do, too.

This first led me to think that there was possibly a bug in Microsoft's implementation of the standard library. But, I found that unlikely seeing as this is their 8th version of it.

So, do you think it is Microsoft's error, or do I have a devious error that will probably hide for a while under GCC and then resurface again?

[Edited by - Ezbez on July 9, 2006 4:14:36 AM]

Share on other sites
Quote:
 Original post by EzbezAlright, I have a fairly major update.I compiled my project with Code::Blocks using GCC to compile. And, surprisingly, it worked perfectly. There's no crash and does what it's supposed to do, too.This first led me to think that there was possibly a bug in Microsoft's implementation of the standard library. But, I found that unlikely seeing as this is their 8th version of it.So, do you think it is Microsoft's error, or do I have a devious error that will probably hide for a while under GCC and then resurface again?

Yes, you have a hidden bug somewhere that corrupts your data. Problems like that are hard to find.