4

1. 症状

Qt Creator 中的调试会话以随机方式意外终止(即,有时它们正常终止),并出现以下错误之一:

  • PC 寄存器不可用(最常见的错误,通常为“Internal error: pc 0×0 in read in psymtab, but not in symtab”)
  • SIGSEV
  • 西吉尔

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

我正在使用 QT Creator 的 MinGW(32 位)在 Win7 64 上运行 Qt Creator 2.6.2 和 Qt 5.0.1。我已经在另一台具有 Win732 位的机器上进行了测试,并且行为是相同的。

根据我在 Qt 论坛上收到的回复,Rebuild 或 Clean + Build 对此问题没有任何明显影响。

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

使用 Process Explorer,我可以看到第二个线程已附加到我的可执行文件(即使我没有创建线程,您也可以在此处查看使用的代码)。

此外,所有错误案例在第二个线程上都有一个 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 运行它(即,使用“run”而不是“debug”),或者如果我从命令行调试它(从命令行启动 gdb),或者如果我从命令行运行它,这个永远不会创建第二个线程,并且可执行文件 + DLL 图像由我的应用程序的主(也是唯一的)线程加载。

在我上面所说的“成功案例”中,即当第二个线程退出时,它会在加载最后一个 DLL 后立即退出,这就是为什么我相信第二个线程只是为了这个加载而创建的。

4

2 回答 2

0

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

于 2014-03-29T21:15:16.240 回答
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

另一种缩小 bug 的方法是阻止注释掉代码部分,直到 bug 消失,然后向后工作,重新添加代码。

最后,找到这样的错误的另一种方法是使用您经常使用的版本控制工具(对吗?)。恢复到没有错误的版本,然后与当前版本进行差异并首先从这些差异开始。

希望有帮助。

于 2013-03-21T15:56:43.877 回答