1

アプリが 1 日中クラッシュする原因を突き止めようとしています。何千もの言葉に値する図なので、このコードを見てください。ヘッダ:

class SandboxedAppStat : public QObject
{
    Q_OBJECT

private slots:
    void pidsTimerTimeout();

public:
    QTimer m_PidsTimer;

    SandboxedAppStat(QObject *parent = NULL);
};

class SandboxedApp : public QObject
{
    Q_OBJECT

private:
    static SandboxedAppStat SandboxedAppStat1;
};

実装:

void SandboxedAppStat::pidsTimerTimeout()
{
    qDebug() << "whatever";
}

SandboxedAppStat::SandboxedAppStat(QObject *parent)
    : QObject(parent)
{
    bool b = QObject::connect(&m_PidsTimer, SIGNAL(timeout()), 
            this, SLOT(pidsTimerTimeout()));
    m_PidsTimer.start(500);
}

SandboxedAppStat SandboxedApp::SandboxedAppStat1;

実際に私がやろうとしているのは、C++ で静的コンストラクターの動作をシミュレートすることです。私が欲しい

QObject::connect(&m_PidsTimer, SIGNAL(timeout()), 
        this, SLOT(pidsTimerTimeout()));
m_PidsTimer.start(500);

静的メンバー SandboxedAppStat1 が初期化されるとすぐに呼び出されます。そのため、上記のコードは SandboxedAppStat のコンストラクターにあります。

ただし、私の問題は、プログラムを実行すると、行に到達するとすぐにクラッシュすることですconnect(&m_PidsTimer, SIGNAL(timeout()), this, SLOT(pidsTimerTimeout()));

エラーコードc0000005(アクセス違反だと思います)。スクリーンショットはこちらhttp://dl.dropbox.com/u/3055964/Untitled.gif

SandboxedAppStat を非静的変数として宣言すると、クラッシュもエラーも発生しません。すべて正常に動作します。

最初に、クラッシュの理由は、QObject::connect を呼び出すには静的メンバーの初期化が早すぎるという事実である可能性があると考えました。そのため、SandboxedAppStat コンストラクターを次のコードで更新しました。

auto *t = this;
QtConcurrent::run([&] () {
    Sleep(3000);
    bool b = QObject::connect(&(t->m_PidsTimer), 
        SIGNAL(timeout()), t, SLOT(pidsTimerTimeout()));
    t->m_PidsTimer.start(500);
});

ご覧のとおり、QObject::connect は、静的な SanboxedAppStat が初期化される 3 秒後に実行されますが、これも役に立ちませんでした。プログラムは 3 秒後にクラッシュします。

私は本当に混乱しています。この問題の原因がわかりません。静的オブジェクト インスタンスでシグナル/スロットを使用できませんか?

MSVC 2010でQt 4.8.0を使用しています。ありがとう

アップデート

これは、クラッシュを再現するための 1 つのヘッダーと 1 つのソース ファイル (HostileFork が提案したように) のみで構成される単純なプロジェクトです。http://dl.dropbox.com/u/3055964/untitled1.zip

4

1 に答える 1

0

pidsTimerTimeoutスロットの定期的な呼び出しをお探しですか、それとも建設中に 1 回だけですか?

クラスが構築されたらシグナルを受信するだけの場合は、QTimer::singleShotまたはを使用してみてくださいQMetaObject::invokeMethod。継続的なタイムアウトが必要ない場合。すべてのシグナルと同様に、シングル ショットは、ウィンドウ システムのイベント キューが処理された後にのみ実行されます。これにより、スロットの実行にわずかな遅延が生じる可能性があります。

MyClass::MyClass()
{
    // Using a zero singles shot.
    QTimer::singleShot( 0, this, SLOT( initialized() ) );

    // or using invoke method.
    QMetaObject::invokeMethod( this, "initialized", Qt::QueuedConnection );

}

このコードをオフィスで使用すると、静的オブジェクトで成功することは間違いありません。

于 2012-07-02T23:41:48.213 に答える