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

QApplication::notifyを間違って解釈している可能性がありますが、Qt イベント ループがクラッシュしたときに GUI オブジェクト (QMessageBox) を作成しようとしているように感じます。それが可能だとは思いません。

例外の安全性のために、私の理解では、 Exception Safety docs のように、 QApplication::exec 関数全体を try-catch シーケンスでラップする必要があります。

qCritical と qWarning を使用してカスタム エラー ハンドラを実装することを検討してください。これらの関数を一時ディレクトリのログ ファイルにリダイレクトして、クラッシュをデバッグするのが好きです。もちろん、例外処理とは異なり、プログラムは依然としてクラッシュしますが、少なくともその理由はわかっています。必要に応じてサンプルコードを提供できます。

于 2013-03-08T17:27:18.737 に答える
0

QMessageBox::exec() は、便利な static メソッド 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 に答える