0

据我了解,在 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 显示之前释放它。但这也没有用。有任何想法吗?

4

2 回答 2

1

I could be interpretting QApplication::notify wrong, but I'm getting the impression that you're attempting to create a GUI object (QMessageBox) when the Qt event loop crashes. I don't believe that's possible.

For exception safety, my understanding is that you have to wrap the whole QApplication::exec function with a try-catch sequence, as in the Exception Safety docs.

Consider implementing a custom error handler using qCritical and qWarning. I like to redirect those functions to a log file in my temp directory to debug crashes. Of course, your program still crashes unlike in exception handling, but at least you know why. I can provide example code if necessary.

于 2013-03-08T17:27:18.737 回答
0

QMessageBox::exec(),由静态便捷方法critical()、warning()等使用,打开一个本地事件循环,只有在消息框关闭后才返回主事件循环。本地事件循环通常是令人讨厌的,在事件处理过程中打开(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") );
于 2013-03-08T13:00:33.483 回答