1. The symptoms
Debugging sessions in Qt Creator terminate unexpectedly, in a random fashion (i.e., sometimes they terminate normally), with one of the following errors:
- PC register is not available (the most common error, usually with “Internal error: pc 0×0 in read in psymtab, but not in symtab”)
- SIGSEV
- SIGILL
The first sign that this is going to happen is when stepping on a line of my code takes me to an assembler window, into NTDLL (usually, ntdll!LdrFindResource_U+60953
).
I’m running Qt Creator 2.6.2 with Qt 5.0.1, using QT Creator’s MinGW (32 bit), on Win7 64. I've since tested on another machine with Win732 bit, and the behaviour is the same.
Following a response I received on the Qt Forums, Rebuild or Clean + Build don't have any noticeable effect on this issue.
2. First analysis
Since the first error was the most common, I searched the web for it, which led me to this. It seemed spot on – there was definitely a SIGTRAP, which led to that error.
However, as I double-checked all my saved debugger logs, I found several occasions where that error didn’t happen (although the SIGTRAP was always there).
3. The pattern
Armed with WinMerge and some patience, I was finally able to perceive a pattern in all the error cases. All the logs (both error and success) had something like this:
>=thread-created,id="2",group-id="i1"
sThread 2 created
which created a 2nd thread, in addition to my app (which was running on thread id=“1”). However, all the success logs had something like this:
>=thread-exited,id="2",group-id="i1"
sThread 2 in group i1 exited
So, I ran a few more more debugging sessions, and checked the running threads when the first breakpoint was hit. On all the error cases, I was getting something like this:
<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
Using Process Explorer, I could see that this second thread was attached to my executable (even though I don’t create threads, you can see the used code here).
Also, all the error cases had a SIGTRAP on that second thread:
>~"[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. Double-check GDB
To determine if this was a GDB issue, I’ve run several command-line debugging sessions, both with and without “-i mi”. There never was any reference to a 2nd thread, and I never had a debugging session terminate unexpectedly, which is why I believe the cause for this issue could be in Qt Creator.
5. Request for help
I’ve downloaded Qt Creator’s source, and I’ve looked for clues there, but I didn’t get very far.
gdbengine.cpp mentions a “stopper thread”, but the only mention I’ve found is here.
Anyone has any idea/pointer about what I should check next?
Thanks for your time.
EDIT:
I still haven't found the cause for this, but after looking at it with Process Monitor, I've got some more data.
The second thread is created to load my app's executable and the DLLs it requires. I've confirmed this second thread is created only when I debug my app from the Qt Creator IDE; if I run it from the IDE (i.e., use "run" instead of "debug"), or if I debug it from the command line (launch gdb from the command line), or if I run it from the command line, this second thread is never created, and the executable + DLL images are loaded by my app's main (and only) thread.
On what I called "success cases" above, i.e., when this second thread exits, it exits immediately after loading the last DLL, which is why I believe this second thread is created only for this loading.
This is not related to any kind of memory management, but to the way how debuggers interrupt processes on Windows. Check this and this urls
http://www.efnetcpp.org/wiki/Heap_Corruption
Are you freeing/deleting something twice or referring to a variable that has been deleted?
The last time I had errors all over the map in a fairly random fashion it was because of Heap Corruption.
Qt often uses a kind of Smart Pointer to keep track of what needs to be deleted and what doesn't. (Keeping track of how many references are opened and stored and when those references get deleted.) I would look at any variables that get shared by multiple objects.
Here are some other Qt resources for debugging:
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
Understanding and using the Qt Object model correctly, and correctly parenting objects can also be helpful in tracking down weird bugs.
http://qt-project.org/doc/qt-4.8/object.html
Another way of narrowing down the bug, is by block commenting out sections of code until the bug disappears, and then work backwards, adding code back in.
And finally another way to find a bug like this, is to make use of the versioning tool that you have been using on a regular basis (right?). Revert back to a version that didn't have the bug, then do a diff with the current version and start with those differences first.
Hope that helps.