崩溃。 QObject :: connect在静态对象实例的构造函数中

时间:2012-04-25 20:07:03

标签: c++ windows visual-studio-2010 qt static-members

我正在试图找出为什么我的应用程序崩溃了一整天。一张价值数千字的图片,所以看看这段代码。部首:

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秒后崩溃。

我真的很困惑,我不明白这个问题的原因是什么。我们不能在静态对象实例中使用信号/槽吗?

我正在使用Qt 4.8.0和MSVC 2010.谢谢

更新

这是一个简单的项目,只包含一个标题和一个源文件(如HostileFork建议的那样)来重现崩溃。 http://dl.dropbox.com/u/3055964/untitled1.zip

1 个答案:

答案 0 :(得分:0)

您是否正在寻找定期拨打pidsTimerTimeout插槽或在施工期间只拨打一次?

如果您希望在课程构建完成后收到信号,请尝试使用QTimer::singleShotQMetaObject::invokeMethod,如果您不需要连续超时。与所有信号一样,只有在处理了窗口系统的事件队列后才会对单个镜头执行操作,这可能会对插槽的执行造成一点延迟。

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

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

}

我们确信我们在办公室使用此代码,并且我们在静态对象方面取得了成功。