Qt应用程序正在崩溃,甚至是调试器模式,这是我得到的全部内容:
ASSERT:文件中的“!isEmpty()” C:\ Qt \ Qt5.5.0 \ 5.5 \ mingw492_32 \ include \ QtCore / qlist.h,第321行
文件中的那一行指向:
inline void removeLast() { Q_ASSERT(!isEmpty()); erase(--end()); }
但我想了解更多信息。就像源代码中正好使用它一样(来自搜索,没有直接调用removeLast()
完成)。
这可能吗?
答案 0 :(得分:3)
如果在调试器中运行程序,它将停止在断言上,并且您将能够检查堆栈跟踪。例如,在GDB中使用此程序:
#include <QList>
int main(int argc,char* argv[])
{
QList<int> my_list;
my_list.append(1);
my_list.pop_back(); // 1
my_list.pop_back(); // 2
return 0;
}
运行时:
(gdb) r
Starting program: /home/leiaz/tmp/qttest/build/proj
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
ASSERT: "!isEmpty()" in file /usr/include/qt/QtCore/qlist.h, line 321
Program received signal SIGABRT, Aborted.
0x00007ffff61275f8 in raise () from /usr/lib/libc.so.6
断言停止调试器,你可以要求堆栈跟踪:
(gdb) backtrace
#0 0x00007ffff61275f8 in raise () from /usr/lib/libc.so.6
#1 0x00007ffff6128a7a in abort () from /usr/lib/libc.so.6
#2 0x00007ffff6dc11e1 in QMessageLogger::fatal(char const*, ...) const () from /usr/lib/libQt5Core.so.5
#3 0x00007ffff6dbc34e in qt_assert(char const*, char const*, int) () from /usr/lib/libQt5Core.so.5
#4 0x00000000004060aa in QList<int>::removeLast (this=0x7fffffffe4d0)
at /usr/include/qt/QtCore/qlist.h:321
#5 0x0000000000405de0 in QList<int>::pop_back (this=0x7fffffffe4d0)
at /usr/include/qt/QtCore/qlist.h:337
#6 0x0000000000405ad4 in main (argc=1, argv=0x7fffffffe5d8) at /home/leiaz/tmp/qttest/main.cc:9
您可以看到removeLast
调用了pop_back
,我的代码从第6帧开始:
(gdb) frame 6
#6 0x0000000000405ad4 in main (argc=1, argv=0x7fffffffe5d8) at /home/leiaz/tmp/qttest/main.cc:9
9 my_list.pop_back(); // 2
在这里,您可以检查该帧中其他变量的值。
如果您使用的是Qt Creator,请参阅Viewing Call Stack Trace。
答案 1 :(得分:1)
就像源代码中正好使用它一样(来自搜索,没有直接调用removeLast())。这可能吗?
不幸的是,assert()
或Q_ASSERT()
宏只显示条件错误,而不是哪个代码导致了这些条件。
特别是如果多次调用和/或从多个地方调用,断言对于检测实际导致它的代码并没有多大帮助。
如果调试器支持isEmpty()
条件,则可以为abort()
条件设置条件断点。
如果您有权访问调试符号,也可以在标准void removeLast()
{
if(isEmpty()) { // <<<<<<<<<<< Put an encapsulating if clause here
return; // <<<<<<<<<<<< set breakpoint
}
Q_ASSERT(!isEmpty()); erase(--end());
}
函数中设置断点。
如果没有,并且您可以完全访问源代码(对于在标题中内联的函数而言),则可以解决该缺陷。我通常采用的方式是暂时将此类代码更改为
awk
并设置调试器断点。当从调试器运行代码时遇到断点时,我将检查调用堆栈以查看它来自何处。