无法找到段错误的根源
编辑:问题已解决。这是(又一种)情况,问题实际上并不在看起来的地方。线索是使用 @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
一些背景: 该映射是指针到指针的映射。具体来说,键是指向 GUI 系统中的窗口的指针,值是指向可以将要打印的信息发送到该窗口的对象的指针。还有一个从可调试对象到窗口的逆映射。原因是,如果窗口关闭,则需要通知可调试对象,以便它不能浪费时间尝试向其发送数据。逆映射是这样的,当管理器(此代码所在的类)从可调试对象接收到数据包时,它知道在哪个窗口中打印信息。
所以问题是为什么两个指针值的比较 < code>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 );
正如你所看到的,我正在打印出要进入的内容和试图从地图中删除的内容的地址,它们与我相对应我会期望所以我不会试图删除失效的值或任何东西。
哦,还有最后一点。这是一个奇怪的怪癖。如果我只打开一个窗口(即只向地图添加一个元素),我可以很好地擦除它。只有在向映射添加两个或多个元素后,尝试删除其中一个元素才会导致分段错误。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在实际比较之前,尝试取消引用 0xfeeefefe 时似乎发生了段错误。
< 的类型有哪些代码>__x 和
__y
?您能否验证写入__x
和__y
的初始值,然后监视内存位置是否有任何更改?另外,如果您可以在
HeapFree
函数上放置一个断点,您也许能够捕获错误的内存引用。It looks like segfault occurs trying to dereference
0xfeeefefe
, before the actual comparison.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.奇怪的怪癖通常代表内存问题。您尝试过运行 valgrind 吗?
您要插入克隆吗?指针是否在映射中插入和删除之间的某个位置被删除?
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?
我正在查看您的回溯,我正在查看它所说的内容
__x=@0x22f778, __y=@0xfeeefefe
这似乎表明 __x 和 __y 是引用。
在这种情况下,尝试测试( __x < __y )可能会取消引用它们,并且取消引用 0xfeeefefe 可能不是一件好事,除非您的机器安装了 beaucoup 内存。
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.