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。谢谢

更新

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

4

1 回答 1

0

您是在寻找定期调用您的pidsTimerTimeout插槽还是在施工期间只调用一次?

如果您希望在构建类后仅接收信号,请尝试使用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 回答