繁体   English   中英

问:如何处理源自Qt类内部的崩溃?

[英]Qt: How to handle a crash originated from inside a Qt class?

我正在做一些关于在基于Qt的应用程序中处理错误的研究,在做了一些关于断言的Qt使用而不是异常抛出的读数后,我得到了以下问题:

Qt类的某些方法会使应用程序在发生错误时立即崩溃。 例如,如果我使用Qt容器(如QList)并调用比容器大小更大的成员,则软件立即关闭:

QList<int> myList;
int itemp = myList.at(1);

//Crash!

现在我不希望在我的应用程序中发生这种情况:如果发生这样的事件,我想处理该事件(即使它只是在错误日志中记录某些内容并稍后关闭该应用程序)。 但是,如果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(); }

这不是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,它什么都不做。

另一种方法是在实际索引之前检查size() 那会让你免于崩溃。 让我给你举个例子:

QList<int> myList;
int itemp = myList.size() ? myList.at(1) : 0;

话虽这么说,记录这个错误的想法值得怀疑。 您应该避免出现此错误,而不是事后处理它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM