Mom*_*gil 4 c++ debugging qt qlist qtcore
我正在做一些关于在基于 Qt 的应用程序中处理错误的研究,在阅读了一些关于 Qt 使用断言而不是异常抛出的文章后,我想到了以下问题:
Qt 类的某些方法会在其中发生错误时使应用程序立即崩溃。例如,如果我使用 Qt 容器(例如 QList)并调用大于容器大小的成员,则软件会立即关闭:
QList<int> myList;
int itemp = myList.at(1);
//Crash!
Run Code Online (Sandbox Code Playgroud)
现在我不希望在我的应用程序中发生这种情况:如果发生这样的事件,我想处理该事件(即使只是在错误日志中记录某些内容并稍后关闭应用程序)。但是,如果 Qt 在我进行任何错误检查之前使软件崩溃,我该怎么做?并且将代码放在 try-catch 中是行不通的,因为 Qt 在发生这种情况时不会抛出任何内容(至少在未启用异常时不会抛出,这是我假装使用的)。有没有办法解决这个问题?
这不是真正的崩溃。这在 Linux 上称为 SIGABRT,等等。您所看到的基本上是 Q_ASSERT_X 的结果:
template <typename T>
inline const T &QList<T>::at(int i) const
{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::at", "index out of range");
return reinterpret_cast<Node *>(p.at(i))->t(); }
Run Code Online (Sandbox Code Playgroud)
这在任何方面都不是特定于 Qt 的,只是通用的 C++,因此处理它的唯一方法本质上是特定于平台的。例如,在带有 POSIX 的 Linux 上,您将编写一个为该信号注册的信号处理程序。例如,您可以查找man signal(7)。看到这个报价:
处理 SIGABRT
在处理这个信号时,您应该记住 abort(3) 函数的工作原理:它使信号上升两次,但第二次 SIGABRT 处理程序恢复到默认状态,因此即使您定义了处理程序,程序也会终止。因此,您实际上有机会在程序终止之前执行 abort(3) 的情况。如前所述,可以通过不退出信号处理程序并使用 longjmp(3) 来不终止程序。
所以,这就是你基本上可以做的:
jmp_buf env;
void sigabrt_handler(int signum)
{
longjmp (env, 1);
}
void handle_func(void (*func)(void))
{
if (setjmp (env) == 0) {
signal(SIGABRT, &sigabrt_handler);
(*func)();
}
else {
qDebug() << "Aborted\n";
}
}
Run Code Online (Sandbox Code Playgroud)
然后你会用你的函数调用这个处理程序:
handle_func(my_func_void_retval_void_args);
Run Code Online (Sandbox Code Playgroud)
同样,您需要在您打算使用的所有平台上实现它。
您也可以忽略它满足这里的宏条件,即已QT_NO_DEBUG定义和QT_FORCE_ASSERT未定义。后者应该是默认值。
#if !defined(Q_ASSERT_X)
# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
# define Q_ASSERT_X(cond, where, what) qt_noop()
# else
# define Q_ASSERT_X(cond, where, what) ((!(cond)) ? qt_assert_x(where, what,__FILE__,__LINE__) : qt_noop())
# endif
#endif
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅其文档:
Q_ASSERT_X 可用于在开发过程中测试前置和后置条件。如果在编译期间定义了 \c QT_NO_DEBUG,则它什么也不做。
另一种方法是在实际索引之前检查size()。那会让你免于崩溃。让我给你举个例子:
QList<int> myList;
int itemp = myList.size() ? myList.at(1) : 0;
Run Code Online (Sandbox Code Playgroud)
话虽如此,记录此错误的想法值得怀疑。您应该避免出现此错误,并且不要事后处理。