“这个”堆栈跟踪中的指针被损坏
我看过这个线程。我的情况略有不同,我正在努力弄清楚 "this"
指针是如何损坏的。
我正在使用 Qt 4.6.2 框架,将他们的 QTreeView
与我自己的模型结合使用。我得到的回溯(86帧长,有很多递归,这就是为什么我没有粘贴整个内容,它在这个 pastebin 只涉及他们的代码。
它最终在 QBasicAtomicInt::deref 中的一些汇编器上出现了段错误,但很明显它有进一步下降,由以下三个帧证明:
#15 0x01420fd3 in QFrame::event (this=0x942bba0, e=0xbf8eb624) at widgets/qframe.cpp:557
#16 0x014bb382 in QAbstractScrollArea::viewportEvent (this=0x4, e=0x93f9240) at widgets/qabstractscrollarea.cpp:1036
#17 0x0156fbd7 in QAbstractItemView::viewportEvent (this=0x942bba0, event=0xbf8eb624) at itemviews/qabstractitemview.cpp:1610
在第 17 帧中,this
是 0x942bb0
在第 16 帧中,this
应该相同,如下所示。在第 17 帧中,它调用了其祖先的相同方法的实现,但是
有趣的是,在第 15 帧中,this
变成了 0x4(同样,第 16 帧调用了其祖先的相同方法的实现) 。函数),“this”指针恢复到0x942bba0
。
如果您查看完整回溯的pastebin,您可能会看到一些“优化后的值”。我现在将 gcc 设置为 -g3 -O0
,因此下次发生这种情况时我可能会有更多内容。但现在我当然不能让它崩溃——这是一个相当难以发生的错误(但修复起来非常重要),所以我认为这并不太可疑。
考虑到优化,this
pointer=0x4
是异常还是绝对错误?奇怪的是,这些 viewportEvent 框架中都没有真正的代码——它们只是对事件类型进行切换,它通过 switch 语句,然后返回其祖先的实现。
Valgrind 似乎没有抛出任何问题,尽管我还没有让它在 Valgrind 中崩溃。
以前有人见过这种行为吗?可能是什么原因造成的?
I have seen this thread. My case is slightly different and I'm struggling to figure out how "this"
pointer is getting corrupted.
I'm using the Qt 4.6.2 framework, using their QTreeView
with my own model. The backtrace I get (86 frames long, with a lot of recursion, that's why I haven't pasted the whole thing in, it's in this pastebin only involves their code.
It finally segfaults on some assembler in QBasicAtomicInt::deref, but it's obvious that it has died further down, evidenced by these three frames:
#15 0x01420fd3 in QFrame::event (this=0x942bba0, e=0xbf8eb624) at widgets/qframe.cpp:557
#16 0x014bb382 in QAbstractScrollArea::viewportEvent (this=0x4, e=0x93f9240) at widgets/qabstractscrollarea.cpp:1036
#17 0x0156fbd7 in QAbstractItemView::viewportEvent (this=0x942bba0, event=0xbf8eb624) at itemviews/qabstractitemview.cpp:1610
In frame 17, this
is 0x942bb0
. In frame 16, this
should be the same, as in frame 17 it's calling its ancestor's implementation of the same method. However this
becomes 0x4.
Interestingly enough in frame 15 (again, frame 16 has called its ancestor's implementation of the same function), the 'this' pointer is restored to 0x942bba0
.
If you looked at the pastebin of the full backtrace, you might see some 'value optimized out'. I had the application compiled with optimization on; I now have gcc set to -g3 -O0
so when it happens next time I might have something more. But of course now I can't make it crash -- it is a fairly difficult bug to make happen (but very important to fix nonetheless) so I don't think that's too suspicious.
Given the optimizations, is that this
pointer=0x4
unusual or definitely wrong? What is odd is that there's no real code in any of these viewportEvent frames -- they simply do a switch on the event's type, it falls through the switch statement, and it returns its ancestor's implementation.
Valgrind doesn't seem to be throwing up any issues, although I haven't made it crash in Valgrind yet.
Has anybody seen this behaviour before? What could be causing it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我以前在调试优化构建时见过这种事情,但它从来没有表明对我来说真正的错误是什么。
首先考虑局部变量会更容易。在非优化的构建中,所有内容在内存中都有其指定的位置,并且必须存储在每行代码之后。这样调试器就可以找到它。在优化的构建中,值可以存在于寄存器中,而无需写入内存。这是优化构建性能改进的主要部分。调试器不理解这一点,并且总是查看内存,因此您经常会看到错误的值。
参数也会发生同样的情况。如果优化器决定在寄存器中传递参数,调试器仍然会查看堆栈帧。更具体地说,在根据调用约定的规则参数所在的位置。
堆栈的下一帧具有正确恢复的值的事实表明生成的指令正在正确处理 this 参数,但调试器只是不知道在哪里查找它。
I have seen this sort of thing before when debugging optimized builds and it has never been an indication of what the real bug is for me.
It is easier to first think about a local variable. In a non-optimized build, everything has its designated place in memory and must be stored after every line of code. This is so the debugger can find it. In an optimized build, values can live in registers without being written to memory. This is a major part of the improved performance of an optimized build. The debugger doesn't understand this and will always look at memory, so you will often see the wrong value.
The same can happen with parameters. If the optimizer decides to pass a parameter in a register, the debugger is still going to look at the stackframe. More specifically, at the location where the parameter would be according to the rules of the calling convention.
The fact that the next frame of the stack has the value properly restored indicates that the generated instructions are dealing with the this parameter correctly, but the debugger just doesn't know where to look for it.