对QVector等容器进行取值、移除等操作导致软件崩溃的原因分析及解决方法

一、问题描述

在使用多线程接收并处理数据时,采用了数据驱动的方式进行数据处理。
即在接收到网络数据时,会先将网络数据放入一个QVector容器中,定义一个容器如下:

QVector<QByteArray>queue_RecvDatas;

接收网络数据放入该容器,如下:

QByteArray data=m_data;
queue_RecvDatas.append(data);

同时,新建一个线程,通过不断判断容器是否为空,达到数据驱动处理数据的效果,如下:

void tcp_receiver_thread::run()
{
    while(1)
    {
        if(!queue_RecvDatas.isEmpty())
        {
            QByteArray data=queue_RecvDatas.first();
            qDebug()<<data;
            queue_ResultDatas.pop_front();
        }
    }
}

处理完数据后,将数据移除QVector容器。
随后出现不断的报错,如下报错:

double free or corruption (out)

或者如下报错:

corrupted size vs prev_size

二、问题分析

分析上述报错,可以得知是内存处理时的异常。
经过排查,可以认定出现问题的可能性有两点。

  1. 处理速度跟不上接收速度时,可能会出现错误。
  2. 在取值或者移除值时,刚好也在做增加操作,就会出问题。
    总之,就是对QVector容器的多个操作起了冲突,导致的软件崩溃。

三、解决方法

为了避免出现多个操作出现冲突,因此需要保证同时对一个容器只有一个操作,笔者又希望保留数据驱动的特点。因此设计如下方法:
首先,全局定义从一个容器,改成两个容器,分别为接收容器和处理容器。再添加一个bool判断,用来保证当处理容器在处理数据时候,接收容器不会给处理容器添加数据,但此时接收容器仍旧在接收网络报文数据。当处理容器为空时,接收容器将累计的网络报文一次性交给处理容器,并将自己清空。
全局定义如下:

    QVector<fRecvData>queue_RecvDatas;//接收缓存区数据
    QVector<fRecvData>queue_ResultDatas;//处理缓存区数据
    bool ifGetNewData;//是否从接收缓存区容器中取数

网络报文接收内容如下:

	QByteArray data=m_data;
    //将从网络缓存区获取的数据放入接收缓存区
    queue_RecvDatas.append(data);
    if(ifGetNewData)
    {
        //当处理缓存区处理完数据,将接收缓存区中的数据放入处理缓存区
        queue_ResultDatas.append(queue_RecvDatas);
        //并将接收缓存区清空
        queue_RecvDatas.clear();
    }

处理容器如下:

void tcp_receiver_thread::run()
{
    while(1)
    {
        if(!queue_ResultDatas.isEmpty())
        {
            ifGetNewData=false;//停止往处理缓存区放入数据
            QByteArray data=queue_ResultDatas.first();
            qDebug()<<data;
            queue_ResultDatas.pop_front();
        }else{
            //当处理缓存区处理完数据,允许往处理缓存区放入数据
            ifGetNewData=true;
        }
    }
}

如此便可避免对容器的操作冲突导致的崩溃。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鱼月半

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值