编辑:问题解决了。这是(另一种)情况,问题并不真正出现在它看起来的地方。线索是使用@0xfeeefefe 作为指向对象的指针。这是释放内存时由 Windows API 函数返回的地址……表明正在操作的对象已被删除。
我在尝试从 std::map 中删除值时收到分段错误,但我终其一生都无法弄清楚原因。从调试器(gdb)我看到:
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; }
但奇怪的部分是对这两个输入值的以下检查:
(gdb) x 0x22f778
0x22f778: 0x025e1ef8
(gdb) x 0xfeeefefe
0xfeeefefe: 0x025e1ef8
一些背景知识:映射是指针到指针的映射。具体来说,key 是一个指向 gui 系统中的窗口的指针,而 value 是一个指向可以发送要打印到该窗口的信息的对象的指针。还有一个从可调试对象到窗口的逆映射。原因是如果窗口关闭,可调试对象需要得到通知,这样它就不会浪费时间尝试向它发送数据。逆映射是,当管理器(这段代码所在的类)从可调试对象接收到数据包时,它知道在哪个窗口中打印信息。
所以问题是为什么两个指针值的比较return( 0x025e1ef8 < 0x025e1ef8 )
会导致错误?
我只尝试在我的代码中的某个时间点擦除内容,并且它不在循环中,因此没有任何迭代器可以破坏。我也只在另一个地方将东西插入到该地图中,并且当插入和擦除东西时,我有打印出来的痕迹,我看不出有什么问题。
我知道这些信息不足以提供真正的帮助,但代码真的很大,我不确定我能做些什么来找出问题所在。如果有建议,我很乐意提供更多信息。我将粘贴代码的一些部分,以便快速了解发生了什么。希望这里有一些东西可以表明我的问题是什么。
这是有问题的部分
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;
}
这是将元素添加到地图的部分
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 );
正如您所看到的,我正在打印正在进入的地址以及试图从地图中删除的地址,并且它们与我期望的一致,因此我不会尝试删除失效的值或任何东西。
哦,还有最后一点。这是一个奇怪的怪癖。如果我只打开一个窗口(即只向地图添加一个元素),我可以很好地删除它。只有在将两个或更多元素添加到地图后,尝试删除其中一个元素才会导致分段错误。