2012-04-25 14 views
1

私のアプリが一日中クラッシュする理由を調べようとしています。数千語分の価値がある画像ですので、このコードを見てください。ヘッダー:クラッシュQObject ::静的オブジェクトインスタンスのコンストラクタに接続する

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++の静的コンストラクタの挙動をシミュレートすることです。スタティックメンバーSandboxedAppStat1が初期化するとすぐに

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

が呼び出されます。そのため、上記のコードはSandboxedAppStatのコンストラクタにあります。

しかし、私の問題は、私はプログラムを実行すると、それは、すぐにそれがエラーコードC0000005(私は推測するアクセス違反)でconnect(&m_PidsTimer, SIGNAL(timeout()), this, SLOT(pidsTimerTimeout()));

ラインに達するとクラッシュするということです。 ここにスクリーンショットhttp://dl.dropbox.com/u/3055964/Untitled.gif

私がSandboxedAppStatを非静的変数として宣言すると、クラッシュはなくエラーもなくなります。すべて正常に動作します。

まず私は、クラッシュの理由は、静的メンバーはQObjectのためにあまりにも早くに初期化されている、という事実かもしれないと思っ::私は次のコードで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); 
}); 

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

私は本当に混乱しています。私はこの問題の原因が何であるか理解していません。静的オブジェクトのインスタンスで信号/スロットを使用することはできませんか?私はMSVC 2010年のおかげ

UPDATE

でのQt 4.8.0を使用してい

はここ(HostileForkが示唆したように)クラッシュを再現するために一つだけのヘッダと一つのソースファイルからなる、単純なプロジェクトです。 http://dl.dropbox.com/u/3055964/untitled1.zip

+0

私はこのコードがコンパイルされるとは思わない。 'bool b = QObject :: connect(&m_PidsTimer)、SIGNAL(timeout())、this、SLOT(pidsTimerTimeout()))'この行を見てください。カッコはよくペアになっていません。 – dschulz

+0

あなたはクラスのプロトタイプと実装ファイルを含む*ちょうど*のヘッダーファイルである最小限のプログラム例を構築しようとしましたか?私はLinux 4.8でこれを行いましたが、クラッシュしませんでしたが、QThreadで起動していないスレッドでQTimerを起動できないという警告がデバッグ出力にありました(これはおそらく以前のタイマーQApplicationループに入るまで)。 – HostileFork

+0

@dschulz、可能であれば、ここに貼り付ける際にいくつかのコードを取り除きました。私は間違いを犯す可能性がありますが、これは画像を変更しません。 – Davita

答えて

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); 

} 

私たちはオフィスでこのコードを使用していますが、私たちは静的オブジェクトで成功しています。

関連する問題