据我了解,处理Qt中事件循环内发生的异常的方法是覆盖QApplication :: notify()并在那里处理它。我试过了,它的确有效:
class Application : public QApplication
{
Q_OBJECT
public:
explicit Application( int& argc, char** argv );
// override to handle out of memory exceptions
bool notify( QObject* receiver, QEvent* e );
signals:
public slots:
private:
char* m_buffer;
};
Application::Application(int &argc, char **argv)
:QApplication( argc, argv )
{
m_buffer = new char[1024*1024];
}
bool Application::notify(QObject *receiver, QEvent *e)
{
try
{
return QApplication::notify( receiver, e );
}
catch( std::bad_alloc& )
{
if ( m_buffer )
{
delete[] m_buffer;
m_buffer = NULL;
}
// calling QMessageBox from here doesn't work
// even if release a load of reserved memory
// don't know why
QMessageBox::critical( NULL, "Exception", "Application out of memory" );
}
但是当消息框出现时(即未正确呈现),该消息框为空白。我想也许这个过程没有足够的记忆。所以我尝试在开始时分配1MB内存(参见上面的m_buffer),然后在显示QMessageBox之前释放它。但这也不起作用。有什么想法吗?
答案 0 :(得分:1)
我可能会解释QApplication::notify错误,但我得到的印象是,当Qt事件循环崩溃时,您正在尝试创建GUI对象(QMessageBox)。我不相信这是可能的。
为了安全异常,我的理解是你必须使用try-catch序列包装整个QApplication :: exec函数,如the Exception Safety docs中所述。
使用qCritical和qWarning考虑implementing a custom error handler。我喜欢将这些函数重定向到临时目录中的日志文件以调试崩溃。当然,与异常处理不同,你的程序仍然崩溃,但至少你知道为什么。如有必要,我可以提供示例代码。
答案 1 :(得分:0)
静态便捷方法critical(),warning()等使用的QMessageBox :: exec()打开一个本地事件循环,只有在消息框关闭后才返回主事件循环。本地事件循环通常很讨厌,在事件处理(QApplication :: notify)中打开更是如此。您最好使用QDialog :: open打开消息框而不阻止,甚至更好地推迟消息框:
在您的申请类中:
Q_INVOKABLE void showMessage( const QString& message ); // in your Application class, does the QMessageBox::critical() call
不是直接调用QMessageBox :: critical(),而是用以下内容替换它:
QMetaObject::invokeMethod( this, "showMessage", Qt::QueuedConnection, Q_ARG(QString, "Application out of memory") );