私有变量在线程启动后消失

时间:2015-06-22 16:29:10

标签: multithreading qt pthreads qt5

问题:

我有一个在线程对象启动时可用的私有变量,但在以后使用时(通过信号和插槽调用)超出了范围。

详细信息:

我有一个应用程序,我在Qt5中为linux和windows开发。 目前它在linux(开发开始)的预期下工作,但现在 我试图在Windows 7上站起来(我最初没有Windows的副本)我遇到了这个问题,在那里(仅限Windows)我的私有变量超出了范围后的线程初始化。

问题:

我的对象/线程结构有什么问题,这样在Linux下变量范围很好,但在windows中没有?我认为这就是"在幕后"东西Qt照顾? (显然不是)

更多细节:

操作顺序如下

  1. 实例化对象
  2. 将对象移动到线程
  3. 获取线程的开始信号并在对象中调用init函数
  4. 稍后,获取数据并向线程对象发出信号
  5. 线程对象处理数据
  6. 概述上述步骤的代码总结如下。

    void MyWorkerClass::init()
    {
        // ... bunchOCode
        procThread = new QThread;                   // <-- procThread - private to MyWorkerClass
        procObj    = new Processor(startupData);    // <-- procObj - private to MyWorkerClass
        procObj->moveToThread(procThread);
        connect(procThread,  SIGNAL(started()),           procObj,    SLOT(doStart()));
        connect(this,        SIGNAL(dataIsReady(void *)), procObj,    SLOT(processMsgs(void *)));
        procThread->start();
        ok = waitforProcSetup();
        // ... Life is good, do more stuff
    }
    
    class Processor : public QObject
    {
        // ... Other
        // ... stuff
        private slots:
            void doStart();
            void processMsgs(void * buffer);
        private:
            QHash<QString, bool> process;
    }
    
    void Processor::doStart()                   // <-- private slot 
    {
        // ... take care of init stuff that couldn't be done in constructor
        // Variable is valid here and I can work with it.
        foreach(site, locations.uniqueKeys()) {
            process[site]    = true;           // <-- works like a champ
            qDebug() << QString("%1 => %2").arg(site).arg(process[site]);
        }
    }
    
    void Processor::processMsgs(void * buffer)   // <-- buffer is malloc'd memory and works fine
    {
        // ... When MyWorkerClass gets some data it emits a signal that is connected
        //     to this private slot.
        // Simply trying to examine the variable causes a segfault (because it's uninitialized here)
         qDebug() << "... processMsgs:" << process.isEmpty();   // <-- wets the bed
    }
    .
    

1 个答案:

答案 0 :(得分:0)

在尝试改进我的问题时,通过遵循评论的人的建议,我发现了发生了什么。我正在努力创建我发布的示例的小型工作版本(感谢Kuba Ober)。我遇到的“错误”是一个可以使用调试行重新创建的分段错误:

qDebug() << "... processMsgs:" << process.isEmpty();   // <-- wets the bed

具体来说,当我第一次调用它时(在线程启动并运行之后),私有QHash变量“process”是可用的

connect(procThread,  SIGNAL(started()),           procObj,    SLOT(doStart()));

但是当我第二次尝试调用它时,同样的变量就像它超出了范围一样

connect(this,        SIGNAL(dataIsReady(void *)), procObj,    SLOT(processMsgs(void *)));

第二次调用的信号(dataIsReady(void *))是一个显式的“emit”,工作者类在收集一些可以处理的数据时会这样做。我试图在示例伪代码的注释中明确说明,但我没有考虑到我所包含的注释代码不会很好地说明,因为它都是灰色的。

真正发生的事情就是我用“数据填充”进程[site]“后,我还在一个quint64数组中循环填充数据。循环过去了1个元素并写入“过程”变量,使它看起来像它已超出范围。在linux中,它完全没巧合,它没有段错误(可能在数组和QHash之间有填充),但是Windows运行时第一次暴露了错误。