views:

215

answers:

3

EDIT: Problem solved. This was (yet another) situation where the problem wasn't really where it looked like it was. The clue was the use of @0xfeeefefe as a pointer to an object. This is an address that is returned by a windows API function when freeing memory... indicating that the object that was being operated on had been deleted.

I'm receiving a segmentation fault while trying to erase a value from a std::map, but I cannot for the life of me figure out why. From the debugger (gdb) I see:

Program received signal SIGSEGV, Segmentation fault.
0x0048785f in std::less<irr::gui::IGUIWindow*>::operator()(irr::gui::IGUIWindow* const&, irr::gui::IGUIWindow* const&) const (this=0x258ab04, __x=@0x22f778, __y=@0xfeeefefe)
at C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_function.h:227
227           { return __x < __y; }

But the weird part is the following examination of those two input values:

(gdb) x 0x22f778
0x22f778:       0x025e1ef8
(gdb) x 0xfeeefefe
0xfeeefefe:     0x025e1ef8

Some background: The map is a mapping of pointers to pointers. Specifically, the key is a pointer to a window in a gui system, and the value is a pointer to an object that may send information to be printed to that window. There is also an inverse map from the debuggable object to the window. The reason is that if the window is closed, the debuggable object needs to be informed so it can not waste time by trying to send data to it. The inverse mapping is so that when the manager (the class this code is inside of) receives a packet from a debuggable object, it knows which window to print the information in.

So the question is why would a comparison of two pointer values, return( 0x025e1ef8 < 0x025e1ef8 ) cause a fault?

I only try to erase things at one point in my code, and it's not in a loop so there aren't any iterators to corrupt. I also only insert things into that map at one other place and I have traces that print out when things are being inserted and erased and I can't see anything wrong with that.

I know this isn't enough information to really help, but the code is really large and I'm not sure what I can do to track down the problem. I would be happy to provide any more information if there are suggestions. I'll paste some of the parts of the code for a quick idea of what's going on. Hopefully there is something in here to indicate what my problem is.

Here's the part with the problem

case EGET_ELEMENT_CLOSED:
{
    IGUIWindow* window =
        static_cast<IGUIWindow*>(event.GUIEvent.Caller);

    if( m_debugMap.find(window) != m_debugMap.end())
    {
        IGuiDebuggable* debug = m_debugMap[window];
        debug->removeListener(this);

        cout << "closing window: " << window << " attached"
                " to debuggable: " << debug << endl;

        m_debugMap.erase(window);    /// segfault here
        m_conMap.erase(debug);       /// if above line commented, segfault here
    }

    m_eventMap.erase(window);    /// if above block commented, segfault here
    window->remove();
    return true;
}

And here's the part where an element is added to the map

IGUIElement*    winElmnt    =
                    m_env->getRootGUIElement()->getElementFromId(0,false);

IGUIElement*    editElmnt   = winElmnt->getElementFromId(1);
IGUIWindow*     window      = static_cast<IGUIWindow*>(winElmnt);

cout << "CModelTesterGui: adding " << window << "(" << winElmnt
     << ") to the debug map with edit box " << editElmnt << endl;

m_conMap[debug]             = static_cast<IGUIEditBox*>(editElmnt);
m_debugMap[window]          = debug;

window->setID(-1);
debug->addListener( this );

As you can see I'm printing out the addresses of what is going into and what is attempting to be erased from the map, and they correspond as I would expect so I'm not trying to erase defunct values or anything.

Oh, and a final note. Here's a weird quirk. If I only open one window (i.e. only add one element to the map) I can erase it fine. It's only after adding two or more elements to the map that trying to erase one of them causes a segmentation fault.

+2  A: 

Oh, and a final note. Here's a weird quirk. If I only open one window (i.e. only add one element to the map) I can erase it fine. It's only after adding two or more elements to the map that trying to erase one of them causes a segmentation fault.

Weird quirk usually stand for memory issues. Have you tried running valgrind?

Are you inserting a clone? Is the pointer being deleted somewhere between insertion and deletion from your map?

Tom
I'm on windows :/...
cheshirekow
cr*p :-( 15chars
Tom
Then use visual studio debugger
leiz
hopefully this problem does not require learning an entirely new IDE
cheshirekow
+2  A: 

It looks like segfault occurs trying to dereference 0xfeeefefe, before the actual comparison.

FEEEFEEE Used by Microsoft's HeapFree() to mark freed heap memory (1)

What are the types of __x and __y? Can you verify the initial values written to __x and __y, and then put a watch on the memory location for any changes?

Also, if you could put a break point on the HeapFree function, you might be able to catch a bad memory reference.

Casey
I tried to put a breakpoint on HeapFree but it says the function is ot defined. Possibly the name is mangled? I'll see if I can find it.
cheshirekow
OMG, thank you. That was exactly the clue I needed. I couldn't find a way to get a trace on HeapFree, but I assumed that some heap was being freed (and it shouldn't had) and that alerted me to the problem. So the class is reference counted, and ->removeListener caused the source object to drop a reference... but it was not properly grabbing the reference when the class was first added.
cheshirekow
+1  A: 

I'm looking at your traceback, and I'm seeing where it says

__x=@0x22f778, __y=@0xfeeefefe

which seems to suggest that __x and __y are references.

That being the case, trying to test ( __x < __y ) may be dereferencing them, and dereferencing 0xfeeefefe might not be such a good thing to do, unless your machine has beaucoup memory installed.

John R. Strohm
Yeah, see Casey's answer. It looks like it's a dummy address used by the win API
cheshirekow