Qt Creator/GDB - 调试会话意外结束

4

1. 症状

在Qt Creator中进行调试会不可预测地终止(即有时它们正常结束),并出现以下一种错误:

  • PC寄存器不可用(最常见的错误,通常显示“内部错误:PC 0×0在读取psymtab时未在symtab中找到”)
  • SIGSEV
  • SIGILL

这将会发生的第一个迹象是,当我步进我的代码的某一行时,它会带我进入汇编窗口,进入NTDLL(通常是ntdll!LdrFindResource_U + 60953)。

我正在运行使用QT Creator的MinGW(32位)的Qt Creator 2.6.2和Qt 5.0.1,在Win7 64上。此后,我在另一台安装了Win732位的机器上进行了测试,结果行为相同。

根据我在Qt论坛上收到的回应,重建或清理+构建对此问题没有任何明显影响。

2. 第一次分析

由于第一个错误最常见,所以我在网上搜索了它,这使我找到了这个。它看起来很准确-肯定会出现SIGTRAP,这会导致该错误。

然而,当我仔细检查所有保存的调试器日志时,我发现有几个场合并没有发生那个错误(尽管SIGTRAP总是存在)。

3. 模式

在WinMerge和一些耐心的帮助下,我终于能够在所有错误情况中感知到一个模式。所有的日志(包括错误和成功)都有类似于下面的内容:

>=thread-created,id="2",group-id="i1"
sThread 2 created

在我的应用程序(运行于线程ID =“1”)之外,创建了第二个线程。然而,所有成功的日志记录都是这样的:

>=thread-exited,id="2",group-id="i1"
sThread 2 in group i1 exited

因此,我运行了几次调试会话,并在第一个断点被命中时检查了运行的线程。在所有错误情况下,我都会得到类似于以下内容的信息:

<455info threads
>&"info threads\n"
>~"  Id   Target Id         Frame \n"
>~"  2    Thread 7160.0x33ec 0x76f1fd71 in ntdll!RtlFindSetBits () from C:\\Windows\\system32\\ntdll.dll\n"
>~"* 1    Thread 7160.0x128c main (argc=1, argv=0xbb30d8) at ..\\Exeample\\main.cpp:10\n"
>455^done

使用“进程资源管理器”,我可以看到这个第二个线程已经附加到我的可执行文件上(即使我没有创建线程,你可以在这里看到被使用的代码)。
此外,所有的错误情况都在第二个线程上出现了SIGTRAP。
>~"[Switching to Thread 7160.0x33ec]\n"
>*stopped,reason="signal-received",signal-name="SIGTRAP",signal-meaning="Trace/breakpoint trap",frame={addr="0x76f1000d",func="ntdll!LdrFindResource_U",args=[],from="C:\\\\Windows\\\\system32\\\\ntdll.dll"},thread-id="2",stopped-threads="all"
dNOTE: INFERIOR SPONTANEOUS STOP

4. 双重检查GDB

为了确定这是否是GDB问题,我运行了多个命令行调试会话,既包括“-i mi”又不包括。从来没有任何关于第二个线程的引用,并且我从未遇到过调试会话意外终止的情况,这就是我认为这个问题的原因可能在Qt Creator中的原因。

5. 请求帮助

我已经下载了Qt Creator的源代码,并在其中寻找线索,但是我没有走得太远。

gdbengine.cpp提到了一个“停止线程”,但我唯一发现的提到它的地方是这里

有人对我下一步应该检查什么有任何想法/指针吗?

感谢你的时间。

编辑:

我仍然没有找到这个问题的原因,但在使用进程监视器查看后,我获得了更多数据。

第二个线程被创建来加载我的应用程序的可执行文件和它需要的DLL。我确认只有当我从Qt Creator IDE调试我的应用程序时,才会创建这个第二个线程。如果我从IDE中运行它(也就是使用“运行”而不是“调试”),或者从命令行调试它(从命令行启动gdb),或者从命令行运行它,就不会创建这个第二个线程,而可执行文件+DLL映像将由我的应用程序的主(唯一)线程加载。

在上面所说的“成功案例”中,也就是当这个第二个线程退出时,它只在加载最后一个DLL后立即退出,这就是我认为这个第二个线程只为此加载而创建的原因。

2个回答

0

http://www.efnetcpp.org/wiki/Heap_Corruption

你是否在释放/删除某个东西两次,或者引用了一个已被删除的变量?

上次当我遇到错误时,它们几乎是随机分布在整个代码中,原因是堆损坏。

Qt经常使用一种智能指针来跟踪需要删除和不需要删除的内容。(跟踪打开和存储的引用数量,以及何时删除这些引用。)我会查看多个对象共享的任何变量。

这里还有一些Qt调试资源:

http://qt-project.org/doc/qt-4.8/debug.html

http://qt-project.org/doc/qt-4.8/qobject.html#dumpObjectInfo

http://qt-project.org/doc/qt-4.8/qobject.html#dumpObjectTree

正确理解和使用Qt对象模型,并正确地设置对象的父子关系,有助于追踪奇怪的错误。

http://qt-project.org/doc/qt-4.8/object.html

另一种缩小错误范围的方法是通过块注释掉代码部分,直到错误消失,然后逆向操作,将代码重新添加回去。
最后,另一种找到这样的错误的方法是利用您定期使用的版本控制工具(对吧?)。回滚到没有错误的版本,然后与当前版本进行差异比较,并首先处理这些差异。
希望这有所帮助。

谢谢,我会查看这些资源。然而,这段代码很简单,只不过是一个QStringBuilder的“Hello, world”,代码如下:https://dev59.com/DGct5IYBdhLWcg3wULzo#12187166 - PCaetano
在Qt 4.8中使用Qt Creator中的MSVS运行您链接的代码,无论是否使用QT_USE_QSTRINGBUILDER宏,都没有出现任何错误。 - phyatt
是的,代码应该没有错误。问题偶尔会在使用gdb进行调试时出现 - 例如,使用MinGW构建;在main()的第一行上设置断点:“QStringList words;”并使用步骤(使用步骤跳过)直到程序退出。有时,它会很好地运行;有时,它会进入NTDLL,并且调试会话最终将以错误终止。 - PCaetano

0

这与任何类型的内存管理无关,而是与调试器在Windows上中断进程的方式有关。请检查thisthis网址。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接