Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QThread eating up memory
Forum Updated to NodeBB v4.3 + New Features

QThread eating up memory

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 3 Posters 804 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    Steve_Lim
    wrote on last edited by Steve_Lim
    #1

    Hi everyone,

    I have created a program which will let a user draw someone onto an image and then be sent to another window to display, something like a whiteboard chat. So I have created 2 threads, one for transmitter and the other for receiver.

    When I first started the program, the memory usage is about 8mb, but as I draw, the memory increases, up until about 13.1mb before it crashes. I got the data from task manager.

    Please do help as I have no idea what is happening.

    The follow are part of my code:

    Transmitter:

        mutex->lock();
    
        // Transmitter ready
        sReady->wakeAll();
    
        // wait for receiver to received ready and ack back to transmitter
        rAck->wait(mutex);
    
        // Transmitter receive ack and ack back to receiver
        sAck->wakeAll();
    
        // Wait for receiver to be ready to receive data
        receive->wait(mutex);
    
        QByteArray c = charQ.dequeue();
        QByteArray data = dataQ.dequeue();
    
        QBitArray localDataBits;
        QBitArray localCharBits;
        localCharBits = byteToBits(c);
        localDataBits = byteToBits(data);
    
        for (int j = 0; j<c.count()*8; j++)
            {
    
                int write = localCharBits.at(j) ? 1 : 0;
                charBits[j] = write;
            }
    
        for (int j = 0; j<data.count()*8; j++)
            {
    
                int write = localDataBits.at(j) ? 1 : 0;
                dataBits[j] = write;
            }
    
        // Transmitter finish sending
        sent->wakeAll();
    
        // Wait for receiver to receive data
        receive->wait(mutex);
        mutex->unlock();
    
    

    Receiver:

        mutex->lock();
    
        // Wait for transmitter to send ready
        sReady->wait(mutex);
    
        // Send ack to transmitter
        rAck->wakeAll();
    
        // Wait for transmitter to send ack
        sAck->wait(mutex);
    
        // Receiver ready to receive
        receive->wakeAll();
    
        // Wait for transmitter to finish sending data
        sent->wait(mutex);
    
        QBitArray readChar;
        readChar.resize(sizeof (QChar)*8); // to ensure it can hold all bits
        for (int n=0; n<readChar.size(); n++)
            {
    
                bool bit = (incomeChar[n]==1) ? true : false;
                readChar.setBit(n, bit);
            }
    
        // deserialise
        QByteArray rChar = bittobyte(readChar);
        QChar c;
        c = deserial<QChar>(rChar);
    
        QBitArray readdata;
        // to resize readata to ensure it can read all necessary bits
        if (c == 'p') { // coords
            readdata.resize(64);
        }
        else if (c == 't') { // toggle drawing and last coords
            readdata.resize(64);
        }
        else if (c == 'w') { // pen width
            readdata.resize(32);
        }
        else if (c == 'c') { // pen colour
            readdata.resize(88);
        }
        else if (c == 'e') { // eraser
            readdata.resize(88);
        }
        else if (c == 'P') { // pen
            readdata.resize(88);
        }
        else if (c == 'r') { // resize canvas
            readdata.resize(64);
        }
        else if (c == 'q') { // canvas colour
            readdata.resize(88);
        }
        else if (c == 'C') { // clear canvas
            readdata.resize(32);
        }
    
        for (int n=0; n<readdata.size(); n++)
            {
    
                bool bit = (incomeData[n]==1) ? true : false;
                readdata.setBit(n, bit);
            }
    
        QByteArray rdata = bittobyte(readdata);
    
        if (c == 'p') { // coords
            emit sendPosition(rdata);
        }
        else if (c == 't') { // toggle drawing and last coords
            emit sendToggle(rdata);
        }
        else if (c == 'w') { // pen width
            emit sendPenWidth(rdata);
        }
        else if (c == 'c') { // pen colour
            emit sendPenColour(rdata);
        }
        else if (c == 'e') { // eraser
            emit sendEraser(rdata);
        }
        else if (c == 'P') { // eraser
            emit sendPen(rdata);
        }
        else if (c == 'r') { // reisze canvas
            emit sendCanvasSize(rdata);
        }
        else if (c == 'q') { // reisze canvas
            emit sendCanvasColour(rdata);
        }
        else if (c == 'C') { // clear canvas
            emit sendClear(rdata);
        }
    
        // Receiver finish reading
        receive->wakeAll();
    
        mutex->unlock();
    
        if (!*complete) { // if window not close, prepare to receive
            emit done(); // call same function again, prepare for another receive when transmitter is ready
        }
    

    main.cpp:

    QWaitCondition *sendState = new QWaitCondition; // transmitter state
    QWaitCondition *receiveState = new QWaitCondition; // receiver state
    // 'transmission medium'
    bool charStream[8];
    bool dataStream[88];
    // 3 way handshake
    QWaitCondition *senderReady = new QWaitCondition;
    QWaitCondition *receiverAck = new QWaitCondition;
    QWaitCondition *senderAck = new QWaitCondition;
    
    bool finish = 0;
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        drawing userWin;
        drawing receiveWin;
    
        userWin.resize(650, 650);
        receiveWin.resize(650, 650);
    
        userWin.type(false); // transmitter window
        receiveWin.type(true); // receiver window
    
        userWin.setWindowTitle("Draw");
        receiveWin.setWindowTitle("Receive");
    
        QThread transmitThread;
        QThread receiveThread;
    
        QMutex mutex;
    
        transmit *transmitter = new transmit();
        receiver *receive = new receiver();
    
        // move each object to their threads
        transmitter->moveToThread(&transmitThread);
        receive->moveToThread(&receiveThread);
    
        // Initialise by passing address of each stuff to transmitter and receiver
        transmitter->init(dataStream, charStream, sendState, receiveState,
                          senderReady, receiverAck, senderAck , &mutex, &finish);
        receive->init(dataStream, charStream, sendState, receiveState,
                      senderReady, receiverAck, senderAck, &mutex, &finish);
    
        // Transmit window to transmitter
        QObject::connect(&userWin, &drawing::sendData, transmitter, &transmit::queue);
    
        // to enable receiver to receive
        QObject::connect(&receiveThread, &QThread::started, receive, &receiver::receiveData);
    
        // Keep receiver running and waiting for data
        QObject::connect(receive, &receiver::done, receive, &receiver::receiveData);
    
        QObject::connect(&userWin, &drawing::windowClose, transmitter, &transmit::done);
        QObject::connect(&receiveWin, &drawing::windowClose, transmitter, &transmit::done);
    
        // connect from receiver to receive window
        QObject::connect(receive, &receiver::sendToggle, &receiveWin, &drawing::toggleDraw);
        QObject::connect(receive, &receiver::sendPosition, &receiveWin, &drawing::onReceivePos);
        QObject::connect(receive, &receiver::sendPenWidth, &receiveWin, &drawing::onPenSize);
        QObject::connect(receive, &receiver::sendClear, &receiveWin, &drawing::onClear);
        QObject::connect(receive, &receiver::sendPenColour, &receiveWin, &drawing::onPenColour);
        QObject::connect(receive, &receiver::sendEraser, &receiveWin, &drawing::onEraser);
        QObject::connect(receive, &receiver::sendPen, &receiveWin, &drawing::onPen);
        QObject::connect(receive, &receiver::sendCanvasSize, &receiveWin, &drawing::onResizeCanvas);
        QObject::connect(receive, &receiver::sendCanvasColour, &receiveWin, &drawing::onCanvasColour);
    
        transmitThread.start();
        receiveThread.start();
    
        userWin.move(250,150);
        receiveWin.move(1050,150);
    
        userWin.show();
        receiveWin.show();
    
        a.exec();
    
        // end Thread and mutex
    
        transmitThread.quit();
        transmitThread.terminate();
    
        receiveThread.quit();
        receiveThread.terminate();
        mutex.~QMutex();
    
        return 0;
    }
    

    Thank you.

    Edit: I have edited the code to my latest version, replacing while loop with QWaitCondition

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #2
      1. Maunally calling destructors is a bad idea in 99.99999999999999999999999% of the cases
      2. You never actually start the threads so I'm not sure what you are expecting.
      3. You are doing a lot of low level stuff that is not necessary/useful

      something like a whiteboard chat

      Probably this example is a good starting point

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      3
      • S Offline
        S Offline
        Steve_Lim
        wrote on last edited by
        #3

        My bad, I forgot to copy the part where it include .start().

        I have just started programming and so most of the stuff are quite sloppy and not necessary. Any advices are welcome.

        I will have a look at the link you sent

        1 Reply Last reply
        0
        • S Offline
          S Offline
          Steve_Lim
          wrote on last edited by
          #4

          I have done some more testing, when I exclude the thread, it works without the memory increasing overtime. But when I added thread, it starts to increase memory whenever the user does something.

          I am passing the values by pointers, does that affect memory?

          1 Reply Last reply
          0
          • S Offline
            S Offline
            Steve_Lim
            wrote on last edited by
            #5

            It seems like qDebug() is causing all the memory leak. Its not really a leak but since it keeps printing, it takes up memory. Now when I remove qDebug(), the drawing on receive window becomes laggy.

            Is there a reason why?

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Hi,

              Rather than looping like that waiting for something to arrive, why not make use of QWaitCondition ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              2
              • S Offline
                S Offline
                Steve_Lim
                wrote on last edited by
                #7

                HI,
                I did some searching and correct me if I am wrong, QWaitCondition when wait is called, it will lock the mutex, and wait for a condition then unlock it. But both my transmitter and receiver are using the same mutex, will that cause any issue? So far I have no luck trying to use it.

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  Steve_Lim
                  wrote on last edited by
                  #8

                  I have successfully remove while loop and replace it with QWaitCondition. The lagging between sending and receiving window has gone.

                  But the memory is still increasing everytime the user draws (using Task Manager). Is this a normal thing? Or there is some memory leak.

                  The receiver will keep on running and be ready to receive whereas the transmitter will wait until user make changes to the canvas.

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    It depends on how you manage your drawing. If it's a new object each time then yes, that's normal as you are using new objects.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    S 1 Reply Last reply
                    0
                    • SGaistS SGaist

                      It depends on how you manage your drawing. If it's a new object each time then yes, that's normal as you are using new objects.

                      S Offline
                      S Offline
                      Steve_Lim
                      wrote on last edited by Steve_Lim
                      #10

                      @SGaist Sorry for being dumb here, but when you say create new object, do you mean creating variables?

                      Like inside my function there's QByteArray A, but it was not destroyed when the program is running so it create more of itself?

                      Could you also please give an example, as I am abit clueless.

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved