Qt/C++ 错误处理
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4661883/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Qt/C++ Error handling
提问by
I've been doing a lot of research about handling errors with Qt/C++ and I'm still as lost as when I started. Maybe I'm looking for an easy way out (like other languages provide). One, in particular, provides for an unhandled exception which I use religiously. When the program encounters a problem, it throws the unhandled exception so that I can create my own error report. That report gets sent from my customers machine to a server online which I then read later.
我一直在做很多关于用 Qt/C++ 处理错误的研究,但我仍然和刚开始时一样迷茫。也许我正在寻找一种简单的出路(就像其他语言提供的那样)。一个,特别是,提供了一个我虔诚地使用的未处理的例外。当程序遇到问题时,它会抛出未处理的异常,以便我可以创建自己的错误报告。该报告从我的客户机器发送到在线服务器,然后我稍后阅读。
The problem that I'm having with C++ is that any error handling that's done has to be thought of BEFORE hand (think try/catch or massive conditionals). In my experience, problems in code are not thought of before hand else there wouldn't be a problem to begin with.
我在 C++ 中遇到的问题是,必须在处理之前考虑任何已完成的错误处理(想想 try/catch 或大量条件)。根据我的经验,代码中的问题是事先没有想到的,否则一开始就不会有问题。
Writing a cross-platform application without a cross-platform error handling/reporting/trace mechanism is a little scary to me.
编写一个没有跨平台错误处理/报告/跟踪机制的跨平台应用程序对我来说有点可怕。
My question is: Is there any kind of Qt or C++ Specific "catch-all" error trapping mechanism that I can use in my application so that, if something does go wrong I can, at least, write a report before it crashes?
我的问题是:是否有任何类型的 Qt 或 C++ 特定的“全能”错误捕获机制可以在我的应用程序中使用,这样,如果出现问题,我至少可以在崩溃之前编写报告?
Example:
例子:
class MainWindow: public QMainWindow
{
[...]
public slots:
void add_clicked();
}
void MainWindow::add_clicked()
{
QFileDialog dlg(this, Qt::Sheet);
QString filename = dlg.getOpenFileName(this);
if(!filename.isEmpty())
{
QStringList path = filename.split(QDir::separator());
QString file = path.at(path.count()); // Index out of range assertion.
if(!lst_tables->openDatabase(filename))
{
[...]
}
}
}
I want this error to be caught as an unhandled exception AND the application to quit without showing the user the default crash window on Windows/Mac operating system. I just want it to quit nicely after writing the assertion message to a file, etc.
我希望将此错误作为未处理的异常捕获,并且应用程序退出而不向用户显示 Windows/Mac 操作系统上的默认崩溃窗口。我只是希望它在将断言消息写入文件等后很好地退出。
采纳答案by Macke
Override QCoreApplication::notify()and add try-catch there. That, and something in main() covers most cases in my experience.
覆盖QCoreApplication::notify()并在那里添加 try-catch 。那,以及 main() 中的某些内容涵盖了我的经验中的大多数情况。
Here's sort-of how I do it. Note that I'm using C++ RTTI here, not Qt's version, but that's just for convenience in our apps. Also, we put up a QMessageBox with the info and a link to our log-file. You should expand according to your own needs.
这是我如何做到的。请注意,我在这里使用的是 C++ RTTI,而不是 Qt 的版本,但这只是为了方便我们的应用程序。此外,我们提供了一个 QMessageBox,其中包含信息和指向我们日志文件的链接。您应该根据自己的需要进行扩展。
bool QMyApplication::notify(QObject* receiver, QEvent* even)
{
try {
return QApplication::notify(receiver, event);
} catch (std::exception &e) {
qFatal("Error %s sending event %s to object %s (%s)",
e.what(), typeid(*event).name(), qPrintable(receiver->objectName()),
typeid(*receiver).name());
} catch (...) {
qFatal("Error <unknown> sending event %s to object %s (%s)",
typeid(*event).name(), qPrintable(receiver->objectName()),
typeid(*receiver).name());
}
// qFatal aborts, so this isn't really necessary
// but you might continue if you use a different logging lib
return false;
}
In addition we use the __try, __except on Windows to catch asyncronous exceptions (access violations). Google Breakpad could probably serve as a cross-platform substitute for that.
此外,我们在 Windows 上使用 __try、__except 来捕获异步异常(访问冲突)。Google Breakpad 可能可以作为跨平台的替代品。
回答by Edward Strange
You can put a catch (...) in or around main() Here's around:
你可以在 main() 里面或周围放一个 catch (...) 这里是周围:
int main() try
{
...
}
catch (std::exception & e)
{
// do something with what...
}
catch (...)
{
// someone threw something undecypherable
}
回答by Macke
Google Breakpadis a cross-platform application error reporting framework. Maybe it helps?
Google Breakpad是一个跨平台的应用程序错误报告框架。也许它有帮助?
(I haven't tried it in our c++/qt apps yet, but I'd love to get around to it someday...)
(我还没有在我们的 c++/qt 应用程序中尝试过它,但我希望有一天能解决它......)
回答by BuvinJ
Qt doesn't generally use, or entirely support exception throwing (if you can belive that!)
Qt 通常不使用或完全不支持异常抛出(如果你能相信的话!)
Check out these links:
查看这些链接:
Why doesn't Qt use exception handling?
http://doc.qt.io/qt-5/exceptionsafety.html
http://doc.qt.io/qt-5/exceptionsafety.html
That said, the answers from @Crazy Eddie and @Macke are pretty good, but don't always work. In particular, I found you can't use either of them from a slot function you've invoked from QML. So, I created a hacky work around for this problem. *Use this in conjunction with theirs - not in place of it.
也就是说,@Crazy Eddie 和@Macke 的答案非常好,但并不总是有效。特别是,我发现您不能从从 QML 调用的槽函数中使用它们中的任何一个。所以,我为这个问题创建了一个 hacky 解决方法。*将此与他们的结合使用 - 而不是代替它。
First, I created class derived from QException, which I'll skip over here, but is something you'll probably want to do. In this post, I just refer to it as "MyQException".
首先,我创建了从 QException 派生的类,在这里我将跳过它,但您可能想要这样做。在这篇文章中,我只是将其称为“MyQException”。
Anyway, add this header for a class called QmlSlotThrower
:
无论如何,为一个名为的类添加这个标题QmlSlotThrower
:
#ifndef QMLSLOTTHROWER_H
#define QMLSLOTTHROWER_H
#include "MyQException.h"
class QmlSlotThrower
{
public:
static QmlSlotThrower *get()
{
static QmlSlotThrower instance;
return &instance;
}
QmlSlotThrower( QmlSlotThrower const& ) = delete;
void operator=( QmlSlotThrower const& ) = delete;
void throwToTop( const MyQException &exception );
private:
QmlSlotThrower(){}
};
static QmlSlotThrower *qmlSlotThrower = QmlSlotThrower::get();
#define throwFromQmlSlot( exc ) qmlSlotThrower->throwToTop( exc ); return;
#endif // QMLSLOTTHROWER_H
Then, it's cpp:
然后是cpp:
#include "QmlSlotThrower.h"
#include <QTimer>
class AsynchronousThrower: public QObject
{
Q_OBJECT
public:
void throwThis( const MyQException &exception )
{
exception_ = exception;
QTimer::singleShot( 0, this, SLOT( throwIt() ) );
}
private slots:
void throwIt(){ throw exception_; }
private:
MyQException exception_;
};
static AsynchronousThrower asycnThrower;
// This is needed to allow the Q_OBJECT macro
// to work in the private classes
#include "QmlSlotThrower.moc"
// --------------------------------
void QmlSlotThrower::throwToTop( const MyQException &exception )
{ asycnThrower.throwThis( exception ); }
Finally, here's an example implementation:
最后,这是一个示例实现:
void someQMLSlot()
{
// Qt has been progressively adding exception handling
// support, but you still cannot throw from a QML
// triggered slot. It causes an uncatchable fatal error!
// As a general rule, don't throw in Qt unless you are
// certain something is there to catch it. You cannot
// count on an uncaught exception handler at a top level
// to always work. This QML problem is a perfect example.
// So this is not an option here!
//throw MyQException( "Something terrible occured!" );
// This work around, however, can be used instead!
//throwFromQmlSlot( MyQException( "Something terrible occured!" ) )
// Or, to be more robust in illustrating how you can still use
// normal throws from nested functions even, you can do this:
try{ throw MyQException( "Something terrible occured!" ); }
catch( const MyQException &e) { throwFromQmlSlot( e ) }
qDebug() << "YOU SHOULD NEVER SEE THIS!!";
}
ONLY USE THE MACRO DIRECTLY FROM YOUR SLOT!
只能直接从您的插槽中使用宏!
回答by Tejas Katakdhond
I prefer error handling using exceptions. Please find the below sample code:
我更喜欢使用异常进行错误处理。请找到以下示例代码:
ErrorStatus ExplodeToLine()
{
var errorStatus = new ErrorStatus();
try
{
errorStatus = fun();
if (!errorStatus.ok())
{
throw new VicException(L"fun failed");
}
errorStatus = fun1();
if (!errorStatus.ok())
{
throw new VicException(L"fun1 failed");
}
errorStatus = fun2();
if (!errorStatus.ok())
{
throw new VicException(L"fun2 failed");
}
errorStatus.setError(ErrorType.OK);
}
catch (VicException vicExp)
{
Log(vicExp.errorMsg());
}
catch (Exception exp)
{
Log(exp.errorMsg());
}
return error_status;
}