• 6089阅读
  • 11回复

[提问]求教一个QT内存写保护问题?? [复制链接]

上一主题 下一主题
离线starter
 
只看楼主 倒序阅读 楼主  发表于: 2012-12-17
关键词: 问题线程事件
通过设置一个定时器实时写入队列,然后在窗口又有鼠标点击事件进行队列写入操作,然而当点击鼠标时会出现异常终止,后来发现是内存错误,原因可能在于定时器写入队列还未完成时,点击事件就对队列进行了写入。

因此我想请教两个问题1,定时器操作和点击事件是两个独立线程机制吗
2,如何对队列进行写保护,也就是说如何确保每一次插入队列是一个原子操作。。
离线jdwx

只看该作者 1楼 发表于: 2012-12-17
回 楼主(starter) 的帖子
分别在两个部分放qdebug,看输出,不就知道怎么回事了。
发帖时要说明:操作系统、Qt版本、编译器,这样能更快的得到回复。
离线starter
只看该作者 2楼 发表于: 2012-12-17
回 1楼(jdwx) 的帖子
我想知道的是解决方法
离线jdwx

只看该作者 3楼 发表于: 2012-12-17
回 2楼(starter) 的帖子
先假设你说的对,问题就在那里,之后想办法证明是这个问题,问题确定了,才有解决办法,
看不见代码,谁知道怎么办?所以才告诉你证明的方法,自己去处理问题。
发帖时要说明:操作系统、Qt版本、编译器,这样能更快的得到回复。
离线kh99827765

只看该作者 4楼 发表于: 2012-12-17
QMutex  进行锁保护……
离线starter
只看该作者 5楼 发表于: 2012-12-18
回 4楼(kh99827765) 的帖子
同一线程也能用QMutex进行锁保护??
离线kh99827765

只看该作者 6楼 发表于: 2012-12-18
回 5楼(starter) 的帖子
通过qDebug()<<QThread::currentThreadId()打印出当前线程号,判断两个事件是否在同一线程……
离线starter
只看该作者 7楼 发表于: 2012-12-18
回 6楼(kh99827765) 的帖子
已经确认了为同一线程,打印的线程号同为0x22b4
离线kh99827765

只看该作者 8楼 发表于: 2012-12-18
回 7楼(starter) 的帖子
楼主附代码出来……
离线starter
只看该作者 9楼 发表于: 2012-12-18
其实代码没什么,一个定时器处理函数,一个处理鼠标点击的槽函数

定时器函数
void MainWnd::packSendData()
{
    QReadWriteLock lock;
    
    DATA_PACK *pdatapack;
    
    int index = 0;
    unsigned short crcValue = 0;
    memset(sendBuf,0,sizeof(sendBuf));
    sendBuf[index++] = 0x01;
    sendBuf[index++] = 0x04;
    sendBuf[index++] = 0x01;
    sendBuf[index++] = 0x00;
    sendBuf[index++] = 0x00;
    sendBuf[index++] = 0x23;
    crcValue = cal_crc((unsigned char*)sendBuf,6);
    sendBuf[index++] = crcValue&0xFF;
    sendBuf[index++] = crcValue>>8;

    pdatapack = new DATA_PACK;
    memcpy(pdatapack->databuf ,sendBuf,8);
    QWriteLocker locker(&lock);
    dataQueue.enqueue(pdatapack);
    locker.unlock();


    
    index = 0;
    sendBuf[index++] = 0x01;
    sendBuf[index++] = 0x04;
    sendBuf[index++] = 0x00;
    sendBuf[index++] = 0x00;
    sendBuf[index++] = 0x00;
    sendBuf[index++] = 0x30;
    crcValue = cal_crc((unsigned char*)sendBuf,6);
    sendBuf[index++] = crcValue&0xFF;
    sendBuf[index++] = crcValue>>8;

    pdatapack = new DATA_PACK;
    memcpy(pdatapack->databuf ,sendBuf,8);
    locker.relock();
    dataQueue.enqueue(pdatapack);
    locker.unlock();

    qDebug()<<QThread::currentThreadId();

}
离线starter
只看该作者 10楼 发表于: 2012-12-18
鼠标点击处理函数
void SysCtrlPage::powerOnModel()
{


    DATA_PACK *pdatapack;

    int index = 0;
    unsigned short crcValue = 0;
    memset(sendBuf,0,sizeof(sendBuf));
    sendBuf[index++] = 0x01;
    sendBuf[index++] = 0x10;
    sendBuf[index++] = 0x00;
    sendBuf[index++] = 0x3d;
    sendBuf[index++] = 0x00;
    sendBuf[index++] = 0x01;
    sendBuf[index++] = 0x02;
    sendBuf[index++] = 0x00;
    sendBuf[index++] = 0x01;
    crcValue = cal_crc((unsigned char*)sendBuf,9);
    sendBuf[index++] = crcValue&0xFF;
    sendBuf[index++] = crcValue>>8;

    pdatapack = new DATA_PACK;
    
    memcpy(pdatapack->databuf ,sendBuf,11);

    if(dataQueue.count()>0)
    {
        while(!dataQueue.empty())
        {
            pdatapack = dataQueue.dequeue();
            delete pdatapack;
        }
    }
    //pmutex->lock();
    
    dataQueue.enqueue(pdatapack);
    
    //pmutex->unlock();
    qDebug()<<"-------"<<QThread::currentThreadId();
    
    

}
离线starter
只看该作者 11楼 发表于: 2012-12-18
已经找到问题了,问题出在鼠标事件处理函数,在dataQueue.enqueue(pdatapack);
前已经将pdatapack  delete了,出现了野指针,将pdatapack = new DATA_PACK;
移到delete处理后面即可
快速回复
限100 字节
 
上一个 下一个