【问题标题】:Release version works unexpectedly - memory races and strange QThread behaviour发布版本意外运行 - 内存竞争和奇怪的 QThread 行为
【发布时间】:2026-01-03 10:00:02
【问题描述】:

我在调试模式下编写了整个应用程序,在这种模式下一切正常。不幸的是,现在当我尝试运行发布应用程序时,发生了两件意想不到的事情。 基地资料: Qt 5.1.1 Qt 创作者 2.8.1 视窗 7 64x 应用程序有第二个线程,它从主线程中更新的缓冲区中解封装数据。

第一个问题 - 内存竞争: 在我的一种方法中,发布版本中发生了奇怪的内存竞争 - 在调试中一切正常。方法如下:

std::vector<double> dataVec;
std::vecotr<unsigned char> frame("U+014-00300027950l");
//EFrame_AccXPos == 1;
dataVec.push_back(decapsulateAcc(frame.begin()+EFrame_AccXPos));

        double Deserializator::decapsulateAcc(std::vector<unsigned char>::iterator pos)
        {
            const char frac[2] = {*(pos+2),*(pos+3)};
            const char integ[] = {*(pos+1)};
            double sign;

            if (*pos == consts::frame::plusSign) {
                sign = 1.0;
            } else {
                sign = -1.0;
            }
            double integer = (std::strtod(integ, 0));
            double fractial = (std::strtod(frac, 0))/100;

            qDebug() << QString::fromStdString(std::string(integ));
                //prints "014Rd??j?i" should be "0 ?s"
            qDebug() << QString::number(integer);
                //prints "14" should be "0"
            qDebug() << QString::number(fractial);
                //prints "0.14" - everything ok.

            return sign*integer+sign*fractial;
        }

这个方法有什么问题?

第二个问题: 在附加线程中,我发出信号来管理它从缓冲区解封装的数据。发出线程后,等待标志更改为 false。当我添加一些 qDebug 打印时 - 它开始工作,但没有它们它会阻塞(即使标志已经是假的)。下面的代码:

    void DataManager::sendPlottingRequest()
    {
        numberOfMessurement++;
        if (numberOfMessurement == plotAfterEquals ) {
            numberOfMessurement = consts::startsFromZero;
            isStillPlotting=true;
            emit requestPlotting(dataForChart);
                //block in next line
            while (isStillPlotting);
            //it starts work when:
            //int i = 0;
            //while (isStillPlotting) {
            //i++
            //if (i == 10000) qDebug() << isStillPlotting;
            //}
        }
    }

void DataManager::continueProcess()
{
    plottingState++;
    if (plottingState == consts::plottingFinished) {
            //program reach this point
        isStillPlotting = false;
        plottingState = consts::startsFromZero;
    }
}

【问题讨论】:

  • 好的 - 首先是 sloved:在表的初始化中应该是 \0 结尾,例如: const char integ[2] = {*(pos+1), '\0'}; .

标签: c++ multithreading qt memory-leaks


【解决方案1】:

while (isStillPlotting); 被优化为if(isStillPlotting)while(true);

您应该将 isStillPlotting 设为 volatile 或使用 atomicInt 代替。

或者您可以从continueProcess() 中的if 发出信号plottingDone(),然后连接执行while 之后代码的槽

【讨论】: