从C ++设置变量时QML内存泄漏

时间:2016-03-11 21:22:34

标签: c++ qt memory memory-leaks qml

我正在使用VS2013在Windows 7上编写QtQuick GUI并尝试使用工具在画布上绘制图形。在我尝试设置我定义的一个画布属性之前,该图表工作得很好。当我这样做时,程序产生一个白色窗口,内存使用量从正常的几百兆增加到几个演出和死亡。

TimeLineGraph.qml

import QtQuick 2.0
import QtCharts 2.0

Item
{
    id: timeLineGraphItem
    objectName: "timeLineGraphItem"

    width: 500
    height: 500

    Canvas
    {
        id: timeLineGraphCanvas
        objectName: "timeLineGraphCanvas"

        width: 500
        height: 500

        // The unitless scale of each tic
        property variant ticMeasures: [.1, .2, .5, 1, 2, 5, 10, 50, 100]

        // Current tic values for both X and Y axis
        property int xTicValue: 1
        property int yTicValue: 1
        property int axisLineWidth: 4
        property int ticLineWidth: 2
        property int ticLength: 300

        // The pixel height and width of the drawn graph
        property int graphHeight: 300;
        property int graphWidth: 300;

        // Where in the widget the 0,0 coordinate of the graph is
        property int graphXStart: 100;
        property int graphYStart: 400;

        property string title: "Default Title"
        property int minTitleSize: 6
        property int minLegendSize: 4
        property int minLabelSize: 4

        property variant ymaxs: [];
        property int maxValue: 100;
        property int numSeconds: 10;
        property int samplesPerSecond: 10;
        property int numSamples: numSeconds * samplesPerSecond;

        Component.onCompleted:
        {
            xTicValue = ticValue(numSeconds);
            yTicValue = ticValue(maxValue);
        }

        //Timer
        //{
        //    id: timeLineGraphTimer;
        //    interval: 5;
        //    repeat: true;
        //    running: true;

        //    onTriggered: timeLineGraphCanvas.myupdate();
        //}

        function newDataReceived(newData)
        {
            console.log("got here 1 - ", newData);
            if(ymaxs.length > numSamples)
            {
                ymaxs.shift();
            }
            console.log("got here 2 - ", maxValue);

            maxValue = newData;

            if (maxValue == newData)
            {
                maxValue = newData;
                //yTicValue = ticValue(maxValue); //<-- Any of these two
                var value = ticValue(maxValue);   //<-- methods will kill
                yTicValue = value;                //<-- this program
                // ticValue(maxValue) //<-- Commenting the previous two
                                      //    lines and uncommenting this
                                      //    causes things to "run" great.
            }
            console.log("got here 3");

            ymaxs.push(newData);
            console.log("got here 4 : ", ymaxs[0]);

            requestPaint();
            console.log("got here 5");
        }

        function ticValue(maxValue)
        {
            var returnValue = 0;

            console.log("ticValue");
            for(var index = 0; index < ticMeasures.length; index++)
            {
                console.log("    ", index, " of ", ticMeasures.length);
                returnValue = maxValue / ticMeasures[index];
                console.log("    ", returnValue, " = ", maxValue, " / ", ticMeasures[index]);

                if((returnValue >= 5) && (returnValue <= 10))
                {
                    returnValue = ticMeasures[index];
                    break;
                }
            }

            console.log("end ticValue");
            return returnValue;
        }
    }
}

tempClass.cpp

#include "tempClass.h"
#include <QtCore/QVariant>
#include <iostream>

tempClass::tempClass(QObject* object)
{
    timeLineGraph = object;
}

void tempClass::onTimer()
{
    std::cout << "onTimer() 1" << std::endl;
    QMetaObject::invokeMethod(timeLineGraph, "newDataReceived", Qt::DirectConnection, Q_ARG(QVariant, QVariant::fromValue(5)));
    std::cout << "onTimer() 2" << std::endl;
}

tempClass.h

#ifndef TEMPCLASS
#define TEMPCLASS

#include <QtCore/QObject>

class tempClass : public QObject
{
    Q_OBJECT

public:
    tempClass(QObject* object);

    public slots:
    void onTimer();

private:
    QObject* timeLineGraph;
};
#endif

的main.cpp

int main(int argc, char *argv[])
{
    QApplication apps(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl::fromLocalFile("main.qml"));

    QObject* object = engine.rootObjects().value(0)->findChild<QObject*>("blargin")->findChild<QObject*>("timeLineGraphCanvas");

    object->setProperty("title", "new title");

    tempClass* tmp = new tempClass(object);

    QTimer* timer = new QTimer();
    timer->setInterval(100);
    timer->setSingleShot(false);
    timer->setTimerType(Qt::CoarseTimer);
    timer->start();

    QObject::connect(timer, SIGNAL(timeout()), tmp, SLOT(onTimer()));

    return apps.exec();
}

在QML文件TimeLIneGraph.qml中,在函数newDataReceived(newData)中,我根据yTicValue函数的返回值设置了ticValue(maxValue)变量。这导致程序内存泄漏并死亡。但是,如果我只是在没有设置yTicValue的情况下调用该函数,程序运行正常,而没有正确设置tic值的好处,因此看起来很奇怪。

我想我错误地调用了函数newDataReceived,但我很困惑。正如您所看到的,我向控制台提供了一些输出语句,而且我总是希望看到每个输出。在这方面,两个围绕tempClass::onTimer的呼叫。 Qt说从不直接设置QML对象变量,因为它不会发出正确的信号。这是我在QML和C ++之间调用或更改内容的唯一警告。

所以,问题是,有没有人知道为什么设置yTicValue变量会导致系统内存泄漏/使用十倍的内存然后死掉?

1 个答案:

答案 0 :(得分:1)

好的,所以经过一番思考并让我重新回到Qt游戏后,我意识到绘制的请求是一个请求,而不是实际绘制的函数调用。问题在技术上是divide by zero error。然而,这是QML没有做的事情。当你除以零时,QML代码只返回INF,而不是死得很厉害。因此,当我在绘制线程(未显示)中循环时,我从一个到INF并尝试绘制无数个行。

所以,我知道你想知道我在哪里零。 xTicValueyTicValue都在ticMeasures数组中分配了一个值。这两个属性也是整数。因此,当ticValue函数正确返回值为.5时,程序会将其截断为零。

所以,经验教训。不要把例外,断言和崩溃等事情视为理所当然,否则你最终会像我一样脸红。