我正在研究如何处理基于Qt的应用程序中的错误,在阅读了一些关于断言的Qt用法而不是异常抛出之后,我提出了以下问题:
Qt类的某些方法在Qt类中发生错误时会使应用程序立即崩溃。例如,如果我使用Qt容器(如QList )并调用大于容器大小的成员,则软件将立即关闭:
QList<int> myList;
int itemp = myList.at(1);
//Crash!现在,我不希望在我的应用程序中发生这种情况:如果发生这样的事件,我希望处理该事件(即使它只是在错误日志中记录某件事情,并在稍后关闭应用程序)。但是,如果Qt在我做任何错误检查之前就让软件崩溃了,我该怎么做呢?而且,将代码放入尝试捕获中是行不通的,因为Qt在发生这种情况时不会抛出任何东西(至少在没有启用异常时是这样的,这就是我假装使用的)。有办法解决这个问题吗?
发布于 2014-07-18 17:51:53
这不是真正的坠机。这在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(); }这绝不是Qt特定的,只是通用的C++,因此处理它的唯一方法是固有的平台特定的。例如,在带有POSIX的Linux上,您可以编写一个为该信号注册的信号处理程序。例如,您可以查找man signal(7)。见这句话:
处理SIGABRT 在处理这个信号时,您应该记住abort(3)函数是如何工作的:它两次提升信号,但是第二次将SIGABRT处理程序恢复到默认状态时,即使您定义了一个处理程序,程序也会终止。因此,在程序终止之前,您实际上有机会在中止(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";
  }
}然后用函数调用这个处理程序:
handle_func(my_func_void_retval_void_args);类似地,您需要在您打算使用的所有平台上实现这一点。
您也可以忽略它,满足这里的宏条件,即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详情见文件:
在开发过程中,Q_ASSERT_X对于测试前后条件非常有用。如果在编译期间定义了\c QT_NO_DEBUG,则它什么也不做。
另一种方法是在实际索引之前对照大小()进行检查。这样你就不会撞车了。让我举一个例子:
QList<int> myList;
int itemp = myList.size() ? myList.at(1) : 0;尽管如此,记录这个错误的想法是值得怀疑的。你应该避免得到这个错误,而不是事后处理它。
https://stackoverflow.com/questions/24830821
复制相似问题